@xdarkicex/openclaw-memory-libravdb 1.4.14 → 1.4.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 +105 -363
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +11 -0
- package/dist/context-engine.d.ts +1 -0
- package/dist/context-engine.js +135 -25
- package/dist/index.d.ts +2 -0
- package/dist/index.js +49 -25
- package/docs/README.md +31 -16
- package/docs/assets/libravdb-logo.svg +14 -0
- package/docs/contributing.md +16 -69
- package/docs/development.md +98 -0
- package/docs/features.md +125 -0
- package/docs/install.md +4 -0
- package/docs/installation.md +79 -272
- package/docs/models.md +37 -46
- package/docs/performance-and-tuning.md +145 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/context-engine.js
CHANGED
|
@@ -30,15 +30,6 @@ function normalizeCompactResult(response) {
|
|
|
30
30
|
},
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
function describeUnexpectedContent(value) {
|
|
34
|
-
try {
|
|
35
|
-
const serialized = JSON.stringify(value);
|
|
36
|
-
return serialized === undefined ? String(value) : serialized;
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return String(value);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
33
|
function stringifyKernelBlock(block) {
|
|
43
34
|
if (!block || typeof block !== "object") {
|
|
44
35
|
return "";
|
|
@@ -69,10 +60,6 @@ function stringifyKernelBlock(block) {
|
|
|
69
60
|
case "image":
|
|
70
61
|
return "[image omitted]";
|
|
71
62
|
default:
|
|
72
|
-
console.warn("[libravdb] unsupported kernel content block", {
|
|
73
|
-
type: record.type,
|
|
74
|
-
block: describeUnexpectedContent(record),
|
|
75
|
-
});
|
|
76
63
|
return typeof record.text === "string" ? record.text : "";
|
|
77
64
|
}
|
|
78
65
|
}
|
|
@@ -81,10 +68,6 @@ function normalizeKernelContent(content) {
|
|
|
81
68
|
return content;
|
|
82
69
|
}
|
|
83
70
|
if (!Array.isArray(content)) {
|
|
84
|
-
console.warn("[libravdb] unexpected kernel content shape", {
|
|
85
|
-
kind: typeof content,
|
|
86
|
-
value: describeUnexpectedContent(content),
|
|
87
|
-
});
|
|
88
71
|
return "";
|
|
89
72
|
}
|
|
90
73
|
return content.map(stringifyKernelBlock).filter((part) => part.length > 0).join("\n");
|
|
@@ -101,6 +84,14 @@ function approximateMessageTokens(message) {
|
|
|
101
84
|
function approximateMessagesTokens(messages) {
|
|
102
85
|
return messages.reduce((sum, message) => sum + approximateMessageTokens(message), 0);
|
|
103
86
|
}
|
|
87
|
+
function normalizeCurrentTokenCount(currentTokenCount) {
|
|
88
|
+
if (typeof currentTokenCount !== "number" ||
|
|
89
|
+
!Number.isFinite(currentTokenCount) ||
|
|
90
|
+
currentTokenCount <= 0) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return Math.max(1, Math.floor(currentTokenCount));
|
|
94
|
+
}
|
|
104
95
|
function normalizeTokenBudget(tokenBudget) {
|
|
105
96
|
if (typeof tokenBudget !== "number" || !Number.isFinite(tokenBudget) || tokenBudget <= 0) {
|
|
106
97
|
return undefined;
|
|
@@ -128,6 +119,33 @@ function resolveDynamicCompactThreshold(tokenBudget, compactThreshold, compactio
|
|
|
128
119
|
const fraction = normalizeThresholdFraction(compactionThresholdFraction);
|
|
129
120
|
return Math.max(1, Math.floor(normalizedBudget * fraction));
|
|
130
121
|
}
|
|
122
|
+
function resolvePredictiveCompactionTarget(params) {
|
|
123
|
+
const currentTokenCount = normalizeCurrentTokenCount(params.currentTokenCount);
|
|
124
|
+
const threshold = normalizeTokenBudget(params.threshold);
|
|
125
|
+
if (currentTokenCount == null || threshold == null || currentTokenCount < threshold) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
const belowThresholdTarget = Math.max(1, threshold - 1);
|
|
129
|
+
return belowThresholdTarget < currentTokenCount
|
|
130
|
+
? belowThresholdTarget
|
|
131
|
+
: Math.max(1, currentTokenCount - 1);
|
|
132
|
+
}
|
|
133
|
+
function logPredictiveCompactionAttempt(params) {
|
|
134
|
+
params.logger.info?.(`LibraVDB predictive compaction trigger phase=${params.phase} sessionId=${params.sessionId} ` +
|
|
135
|
+
`currentTokenCount=${params.currentTokenCount} threshold=${params.threshold} ` +
|
|
136
|
+
`targetSize=${params.targetSize} tokenBudget=${params.tokenBudget ?? "unknown"}`);
|
|
137
|
+
}
|
|
138
|
+
function logPredictiveCompactionOutcome(params) {
|
|
139
|
+
const message = `LibraVDB predictive compaction ${params.compacted ? "completed" : "did not compact"} ` +
|
|
140
|
+
`phase=${params.phase} sessionId=${params.sessionId} currentTokenCount=${params.currentTokenCount} ` +
|
|
141
|
+
`threshold=${params.threshold} targetSize=${params.targetSize} tokenBudget=${params.tokenBudget ?? "unknown"}` +
|
|
142
|
+
(params.reason ? ` reason=${params.reason}` : "");
|
|
143
|
+
if (params.compacted) {
|
|
144
|
+
params.logger.info?.(message);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
params.logger.warn?.(message);
|
|
148
|
+
}
|
|
131
149
|
function truncateContentToTokenBudget(content, tokenBudget) {
|
|
132
150
|
if (tokenBudget <= 0)
|
|
133
151
|
return "";
|
|
@@ -191,6 +209,10 @@ function buildBudgetFallbackContext(messages, tokenBudget) {
|
|
|
191
209
|
systemPromptAddition: "",
|
|
192
210
|
};
|
|
193
211
|
}
|
|
212
|
+
function resolvePredictiveCompactionTokenCount(args) {
|
|
213
|
+
return (normalizeCurrentTokenCount(args.currentTokenCount) ??
|
|
214
|
+
approximateMessagesTokens(args.messages) + approximateTokenCount(args.prompt ?? ""));
|
|
215
|
+
}
|
|
194
216
|
export function normalizeKernelMessage(message) {
|
|
195
217
|
return {
|
|
196
218
|
role: message.role,
|
|
@@ -263,7 +285,12 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
263
285
|
sessionId: requireSessionId(args.sessionId, "compact"),
|
|
264
286
|
force: args.force,
|
|
265
287
|
...(typeof targetSize === "number" ? { targetSize } : {}),
|
|
266
|
-
...(
|
|
288
|
+
...(() => {
|
|
289
|
+
const normalizedCurrentTokenCount = normalizeCurrentTokenCount(args.currentTokenCount);
|
|
290
|
+
return normalizedCurrentTokenCount != null
|
|
291
|
+
? { currentTokenCount: normalizedCurrentTokenCount }
|
|
292
|
+
: {};
|
|
293
|
+
})(),
|
|
267
294
|
...(typeof cfg.continuityMinTurns === "number"
|
|
268
295
|
? { continuityMinTurns: cfg.continuityMinTurns }
|
|
269
296
|
: {}),
|
|
@@ -293,6 +320,45 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
293
320
|
};
|
|
294
321
|
}
|
|
295
322
|
}
|
|
323
|
+
async function performAfterTurnPredictiveCompaction(args) {
|
|
324
|
+
const dynamicCompactThreshold = getDynamicCompactThreshold(args.tokenBudget);
|
|
325
|
+
const predictiveTargetSize = resolvePredictiveCompactionTarget({
|
|
326
|
+
currentTokenCount: args.currentTokenCount,
|
|
327
|
+
threshold: dynamicCompactThreshold,
|
|
328
|
+
});
|
|
329
|
+
if (args.currentTokenCount == null ||
|
|
330
|
+
dynamicCompactThreshold == null ||
|
|
331
|
+
predictiveTargetSize == null) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
logPredictiveCompactionAttempt({
|
|
335
|
+
logger,
|
|
336
|
+
phase: "afterTurn",
|
|
337
|
+
sessionId: args.sessionId,
|
|
338
|
+
currentTokenCount: args.currentTokenCount,
|
|
339
|
+
threshold: dynamicCompactThreshold,
|
|
340
|
+
targetSize: predictiveTargetSize,
|
|
341
|
+
tokenBudget: args.tokenBudget,
|
|
342
|
+
});
|
|
343
|
+
const compactionResult = await runCompaction({
|
|
344
|
+
sessionId: args.sessionId,
|
|
345
|
+
targetSize: predictiveTargetSize,
|
|
346
|
+
tokenBudget: args.tokenBudget,
|
|
347
|
+
force: true,
|
|
348
|
+
currentTokenCount: args.currentTokenCount,
|
|
349
|
+
});
|
|
350
|
+
logPredictiveCompactionOutcome({
|
|
351
|
+
logger,
|
|
352
|
+
phase: "afterTurn",
|
|
353
|
+
sessionId: args.sessionId,
|
|
354
|
+
currentTokenCount: args.currentTokenCount,
|
|
355
|
+
threshold: dynamicCompactThreshold,
|
|
356
|
+
targetSize: predictiveTargetSize,
|
|
357
|
+
tokenBudget: args.tokenBudget,
|
|
358
|
+
compacted: compactionResult.compacted,
|
|
359
|
+
reason: compactionResult.reason,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
296
362
|
return {
|
|
297
363
|
info: { id: "libravdb-memory", name: "LibraVDB Memory", ownsCompaction: true },
|
|
298
364
|
ownsCompaction: true,
|
|
@@ -337,18 +403,47 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
337
403
|
},
|
|
338
404
|
async assemble(args) {
|
|
339
405
|
const messages = normalizeKernelMessages(args.messages);
|
|
340
|
-
const currentContextTokens =
|
|
406
|
+
const currentContextTokens = resolvePredictiveCompactionTokenCount({
|
|
407
|
+
currentTokenCount: args.currentTokenCount,
|
|
408
|
+
messages,
|
|
409
|
+
prompt: args.prompt,
|
|
410
|
+
});
|
|
341
411
|
const dynamicCompactThreshold = getDynamicCompactThreshold(args.tokenBudget);
|
|
342
|
-
|
|
343
|
-
currentContextTokens
|
|
412
|
+
const predictiveTargetSize = resolvePredictiveCompactionTarget({
|
|
413
|
+
currentTokenCount: currentContextTokens,
|
|
414
|
+
threshold: dynamicCompactThreshold,
|
|
415
|
+
});
|
|
416
|
+
if (dynamicCompactThreshold != null && predictiveTargetSize != null) {
|
|
417
|
+
logPredictiveCompactionAttempt({
|
|
418
|
+
logger,
|
|
419
|
+
phase: "assemble",
|
|
420
|
+
sessionId: args.sessionId,
|
|
421
|
+
currentTokenCount: currentContextTokens,
|
|
422
|
+
threshold: dynamicCompactThreshold,
|
|
423
|
+
targetSize: predictiveTargetSize,
|
|
424
|
+
tokenBudget: args.tokenBudget,
|
|
425
|
+
});
|
|
344
426
|
const compactionResult = await runCompaction({
|
|
345
427
|
sessionId: args.sessionId,
|
|
428
|
+
targetSize: predictiveTargetSize,
|
|
346
429
|
tokenBudget: args.tokenBudget,
|
|
347
430
|
force: true,
|
|
348
431
|
currentTokenCount: currentContextTokens,
|
|
349
432
|
});
|
|
350
|
-
|
|
351
|
-
logger
|
|
433
|
+
logPredictiveCompactionOutcome({
|
|
434
|
+
logger,
|
|
435
|
+
phase: "assemble",
|
|
436
|
+
sessionId: args.sessionId,
|
|
437
|
+
currentTokenCount: currentContextTokens,
|
|
438
|
+
threshold: dynamicCompactThreshold,
|
|
439
|
+
targetSize: predictiveTargetSize,
|
|
440
|
+
tokenBudget: args.tokenBudget,
|
|
441
|
+
compacted: compactionResult.compacted,
|
|
442
|
+
reason: compactionResult.reason,
|
|
443
|
+
});
|
|
444
|
+
if (!compactionResult.ok) {
|
|
445
|
+
logger.warn?.(`LibraVDB predictive compaction blocked assemble path at ${currentContextTokens} tokens ` +
|
|
446
|
+
`(threshold=${dynamicCompactThreshold}): ${compactionResult.reason ?? "compaction failed"}`);
|
|
352
447
|
return buildBudgetFallbackContext(messages, args.tokenBudget);
|
|
353
448
|
}
|
|
354
449
|
}
|
|
@@ -396,8 +491,11 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
396
491
|
async afterTurn(args) {
|
|
397
492
|
const messages = normalizeKernelMessages(args.messages);
|
|
398
493
|
const kernel = runtime.getKernel();
|
|
494
|
+
const currentTokenCount = normalizeCurrentTokenCount(typeof args.runtimeContext?.currentTokenCount === "number"
|
|
495
|
+
? args.runtimeContext.currentTokenCount
|
|
496
|
+
: undefined);
|
|
399
497
|
if (kernel) {
|
|
400
|
-
|
|
498
|
+
const result = await kernel.afterTurn({
|
|
401
499
|
sessionId: args.sessionId,
|
|
402
500
|
sessionKey: args.sessionKey,
|
|
403
501
|
userId: args.userId,
|
|
@@ -405,12 +503,24 @@ export function buildContextEngineFactory(runtime, cfg, recallCache, logger = co
|
|
|
405
503
|
prePromptMessageCount: args.prePromptMessageCount,
|
|
406
504
|
isHeartbeat: args.isHeartbeat,
|
|
407
505
|
});
|
|
506
|
+
await performAfterTurnPredictiveCompaction({
|
|
507
|
+
sessionId: args.sessionId,
|
|
508
|
+
tokenBudget: args.tokenBudget,
|
|
509
|
+
currentTokenCount,
|
|
510
|
+
});
|
|
511
|
+
return result;
|
|
408
512
|
}
|
|
409
513
|
const rpc = await runtime.getRpc();
|
|
410
|
-
|
|
514
|
+
const result = await rpc.call("after_turn_kernel", {
|
|
411
515
|
...args,
|
|
412
516
|
messages,
|
|
413
517
|
});
|
|
518
|
+
await performAfterTurnPredictiveCompaction({
|
|
519
|
+
sessionId: args.sessionId,
|
|
520
|
+
tokenBudget: args.tokenBudget,
|
|
521
|
+
currentTokenCount,
|
|
522
|
+
});
|
|
523
|
+
return result;
|
|
414
524
|
}
|
|
415
525
|
};
|
|
416
526
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -8,33 +8,57 @@ import { buildMemoryPromptSection } from "./memory-provider.js";
|
|
|
8
8
|
import { buildMemoryRuntimeBridge } from "./memory-runtime.js";
|
|
9
9
|
import { createRecallCache } from "./recall-cache.js";
|
|
10
10
|
import { createPluginRuntime } from "./plugin-runtime.js";
|
|
11
|
+
export const MEMORY_ID = "libravdb-memory";
|
|
12
|
+
export function register(api) {
|
|
13
|
+
const isFullMode = api.registrationMode === "full";
|
|
14
|
+
const cfg = api.pluginConfig;
|
|
15
|
+
// Null in non-full mode — cli.ts skips action handlers when runtime is null.
|
|
16
|
+
const runtimeOrNull = isFullMode
|
|
17
|
+
? createPluginRuntime(cfg, api.logger ?? console)
|
|
18
|
+
: null;
|
|
19
|
+
registerMemoryCli(api, runtimeOrNull, cfg, api.logger ?? console);
|
|
20
|
+
if (!isFullMode)
|
|
21
|
+
return;
|
|
22
|
+
// TypeScript can't narrow through the ternary, so re-bind and guard.
|
|
23
|
+
const runtime = runtimeOrNull;
|
|
24
|
+
if (!runtime)
|
|
25
|
+
return; // unreachable but satisfies the type checker
|
|
26
|
+
const recallCache = createRecallCache();
|
|
27
|
+
// Exclusive slot check: refuse to register if another plugin owns the memory slot.
|
|
28
|
+
// plugins.slots.memory is the only configurable slot; context engine exclusivity
|
|
29
|
+
// is enforced by the registry at runtime (no config surface for it).
|
|
30
|
+
// "none" means memory is disabled — not a conflict, allow registration.
|
|
31
|
+
const memSlot = api.config?.plugins?.slots?.memory;
|
|
32
|
+
if (memSlot && memSlot !== MEMORY_ID && memSlot !== "none") {
|
|
33
|
+
throw new Error(`[libravdb-memory] plugins.slots.memory is "${memSlot}". ` +
|
|
34
|
+
`Set it to "libravdb-memory" before enabling this plugin.`);
|
|
35
|
+
}
|
|
36
|
+
// Migrated from three legacy calls to a single registerMemoryCapability.
|
|
37
|
+
api.registerMemoryCapability(MEMORY_ID, {
|
|
38
|
+
promptBuilder: buildMemoryPromptSection(runtime.getRpc, cfg, recallCache),
|
|
39
|
+
runtime: buildMemoryRuntimeBridge(runtime.getRpc, cfg),
|
|
40
|
+
});
|
|
41
|
+
api.registerContextEngine(MEMORY_ID, () => buildContextEngineFactory(runtime, cfg, recallCache, api.logger ?? console));
|
|
42
|
+
const markdownIngestion = createMarkdownIngestionHandle(cfg, runtime.getRpc, api.logger ?? console);
|
|
43
|
+
const dreamPromotion = createDreamPromotionHandle(cfg, runtime.getRpc, api.logger ?? console);
|
|
44
|
+
void markdownIngestion.start().catch((error) => {
|
|
45
|
+
api.logger?.warn?.(`LibraVDB markdown ingestion failed to start: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
|
+
});
|
|
47
|
+
void dreamPromotion.start().catch((error) => {
|
|
48
|
+
api.logger?.warn?.(`LibraVDB dream promotion failed to start: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
});
|
|
50
|
+
api.on("before_reset", createBeforeResetHook(runtime, api.logger ?? console));
|
|
51
|
+
api.on("session_end", createSessionEndHook(runtime, api.logger ?? console));
|
|
52
|
+
api.on("gateway_stop", async () => {
|
|
53
|
+
await dreamPromotion.stop();
|
|
54
|
+
await markdownIngestion.stop();
|
|
55
|
+
await runtime.shutdown();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
11
58
|
export default definePluginEntry({
|
|
12
|
-
id:
|
|
59
|
+
id: MEMORY_ID,
|
|
13
60
|
name: "LibraVDB Memory",
|
|
14
61
|
description: "Persistent vector memory with three-tier hybrid scoring",
|
|
15
62
|
kind: ["memory", "context-engine"],
|
|
16
|
-
register
|
|
17
|
-
const cfg = api.pluginConfig;
|
|
18
|
-
const recallCache = createRecallCache();
|
|
19
|
-
const runtime = createPluginRuntime(cfg, api.logger ?? console);
|
|
20
|
-
const markdownIngestion = createMarkdownIngestionHandle(cfg, runtime.getRpc, api.logger ?? console);
|
|
21
|
-
const dreamPromotion = createDreamPromotionHandle(cfg, runtime.getRpc, api.logger ?? console);
|
|
22
|
-
void markdownIngestion.start().catch((error) => {
|
|
23
|
-
api.logger?.warn?.(`LibraVDB markdown ingestion failed to start: ${error instanceof Error ? error.message : String(error)}`);
|
|
24
|
-
});
|
|
25
|
-
void dreamPromotion.start().catch((error) => {
|
|
26
|
-
api.logger?.warn?.(`LibraVDB dream promotion failed to start: ${error instanceof Error ? error.message : String(error)}`);
|
|
27
|
-
});
|
|
28
|
-
registerMemoryCli(api, runtime, cfg, api.logger ?? console);
|
|
29
|
-
api.registerContextEngine("libravdb-memory", () => buildContextEngineFactory(runtime, cfg, recallCache, api.logger ?? console));
|
|
30
|
-
api.registerMemoryPromptSection(buildMemoryPromptSection(runtime.getRpc, cfg, recallCache));
|
|
31
|
-
api.registerMemoryRuntime?.(buildMemoryRuntimeBridge(runtime.getRpc, cfg));
|
|
32
|
-
api.on("before_reset", createBeforeResetHook(runtime, api.logger ?? console));
|
|
33
|
-
api.on("session_end", createSessionEndHook(runtime, api.logger ?? console));
|
|
34
|
-
api.on("gateway_stop", async () => {
|
|
35
|
-
await dreamPromotion.stop();
|
|
36
|
-
await markdownIngestion.stop();
|
|
37
|
-
await runtime.shutdown();
|
|
38
|
-
});
|
|
39
|
-
},
|
|
63
|
+
register,
|
|
40
64
|
});
|
package/docs/README.md
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
This
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
1
|
+
# LibraVDB Memory Docs
|
|
2
|
+
|
|
3
|
+
This directory holds the operational and design docs for the LibraVDB Memory
|
|
4
|
+
OpenClaw plugin. The root README is the public entry point; these files go
|
|
5
|
+
deeper by goal.
|
|
6
|
+
|
|
7
|
+
## Start Here
|
|
8
|
+
|
|
9
|
+
- [Install](./install.md) - shortest supported install and daemon lifecycle path.
|
|
10
|
+
- [Installation reference](./installation.md) - requirements, activation, verification, and troubleshooting.
|
|
11
|
+
- [Uninstall](./uninstall.md) - safe disable, daemon shutdown, package removal, and optional data cleanup.
|
|
12
|
+
|
|
13
|
+
## Understand The System
|
|
14
|
+
|
|
15
|
+
- [Problem](./problem.md) - why this plugin replaces the stock memory lifecycle.
|
|
16
|
+
- [Architecture](./architecture.md) - plugin, sidecar, storage, retrieval, and compaction overview.
|
|
17
|
+
- [Dependency rationale](./dependencies.md) - why LibraVDB and slab-style storage fit this workload.
|
|
18
|
+
- [Architecture decisions](./architecture-decisions/README.md) - accepted ADRs.
|
|
19
|
+
|
|
20
|
+
## Configure And Operate
|
|
21
|
+
|
|
22
|
+
- [Features](./features.md) - markdown ingestion, Obsidian ingestion, dream promotion, and memory CLI commands.
|
|
23
|
+
- [Security](./security.md) - trust boundaries, untrusted-memory framing, collection isolation, and deletion limits.
|
|
24
|
+
- [Embedding profiles](./embedding-profiles.md) - shipped embedding profile metadata and defaults.
|
|
25
|
+
- [Models](./models.md) - local ONNX model strategy and summarization roles.
|
|
26
|
+
|
|
27
|
+
## Advanced And Source Docs
|
|
28
|
+
|
|
29
|
+
- [Performance and tuning](./performance-and-tuning.md) - resource expectations and tuning knobs.
|
|
30
|
+
- [Development](./development.md) - source setup, local daemon builds, generated IPC files, and validation commands.
|
|
31
|
+
- [Contributing](./contributing.md) - contributor workflow and repository expectations.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="170" viewBox="0 0 1280 170" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">LibraVDB</title>
|
|
3
|
+
<desc id="desc">Dark purple LibraVDB wordmark.</desc>
|
|
4
|
+
<rect width="1280" height="170" fill="none"/>
|
|
5
|
+
<text
|
|
6
|
+
x="640"
|
|
7
|
+
y="128"
|
|
8
|
+
text-anchor="middle"
|
|
9
|
+
fill="#5B21B6"
|
|
10
|
+
font-family="Inter, Avenir Next, Helvetica Neue, Arial, sans-serif"
|
|
11
|
+
font-size="150"
|
|
12
|
+
font-weight="800"
|
|
13
|
+
letter-spacing="0">LibraVDB</text>
|
|
14
|
+
</svg>
|
package/docs/contributing.md
CHANGED
|
@@ -1,88 +1,35 @@
|
|
|
1
1
|
# Contributing
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use [Development](./development.md) for source setup, local daemon preparation,
|
|
4
|
+
generated IPC files, and validation commands. This document covers contribution
|
|
5
|
+
expectations.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
- `pnpm`
|
|
7
|
-
- OpenClaw CLI for end-to-end plugin testing
|
|
7
|
+
## Baseline Checks
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
TypeScript and unit checks:
|
|
9
|
+
Before opening a PR:
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
12
|
pnpm check
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Integration tests:
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm run test:integration
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Plugin integration tests:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
13
|
npm run test:integration
|
|
27
14
|
```
|
|
28
15
|
|
|
29
|
-
|
|
16
|
+
Integration tests require a running daemon or a prepared local daemon binary.
|
|
17
|
+
Use:
|
|
30
18
|
|
|
31
19
|
```bash
|
|
32
20
|
bash scripts/build-daemon.sh
|
|
33
21
|
```
|
|
34
22
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Supported inputs:
|
|
38
|
-
|
|
39
|
-
- installed daemon on `PATH` such as `brew install libravdbd`
|
|
40
|
-
- `LIBRAVDBD_BINARY_PATH=/path/to/libravdbd`
|
|
41
|
-
- `LIBRAVDBD_SOURCE_DIR=/path/to/libravdbd` to build from your private local daemon repo
|
|
42
|
-
|
|
43
|
-
For daemon-internal Go development and release work, use the separate `libravdbd` repository.
|
|
23
|
+
## Behavioral Changes
|
|
44
24
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- empty-memory novelty
|
|
50
|
-
- saturation veto
|
|
51
|
-
- convex boundedness
|
|
52
|
-
- conversational collapse at `T = 0`
|
|
53
|
-
- technical collapse at `T = 1`
|
|
54
|
-
- non-overfiring conversational structure on code
|
|
55
|
-
|
|
56
|
-
If you add a new signal, it must preserve those invariants.
|
|
57
|
-
|
|
58
|
-
## Calibration Coverage
|
|
59
|
-
|
|
60
|
-
There is not yet a dedicated `gate_calibration_test.go` golden set in the
|
|
61
|
-
repository. Current gating correctness is enforced by the invariant suite in
|
|
62
|
-
`libravdbd/compact/gate_test.go`.
|
|
63
|
-
|
|
64
|
-
If you introduce new signals or change weighting behavior, do not only update
|
|
65
|
-
the implementation. Add one of:
|
|
66
|
-
|
|
67
|
-
- a new invariant if the change alters a structural property of the gate
|
|
68
|
-
- a dedicated calibration/golden test file if the change adds new labeled
|
|
69
|
-
examples or expected decompositions
|
|
70
|
-
|
|
71
|
-
Do not rewrite expectations just to make regressions disappear.
|
|
25
|
+
If you change retrieval, compaction, or ranking behavior, add or update the
|
|
26
|
+
matching validation coverage and avoid weakening checks just to hide a
|
|
27
|
+
regression.
|
|
72
28
|
|
|
73
29
|
## PR Expectations
|
|
74
30
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
- any retrieval math or gating change must be reflected in the private design notes
|
|
81
|
-
|
|
82
|
-
## Release Versioning
|
|
83
|
-
|
|
84
|
-
`package.json` is the source of truth for the release version.
|
|
85
|
-
|
|
86
|
-
The release automation syncs `openclaw.plugin.json` from `package.json` during the
|
|
87
|
-
auto-bump/tag flow, and the publish workflow refuses to publish if the Git tag,
|
|
88
|
-
`package.json`, and `openclaw.plugin.json` versions do not all match.
|
|
31
|
+
- Keep plugin lifecycle and daemon lifecycle separate.
|
|
32
|
+
- Include focused docs updates for user-visible behavior or config changes.
|
|
33
|
+
- Keep internal design changes reflected in the appropriate design notes.
|
|
34
|
+
- Do not add install-time daemon bootstrap to the npm/OpenClaw package without
|
|
35
|
+
documenting the security and distribution trade-off.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
This document covers source setup and repository maintenance tasks. For user
|
|
4
|
+
installation, use [Install](./install.md).
|
|
5
|
+
|
|
6
|
+
## Prerequisites
|
|
7
|
+
|
|
8
|
+
- Node.js `>= 22`
|
|
9
|
+
- `pnpm`
|
|
10
|
+
- OpenClaw CLI for end-to-end plugin testing
|
|
11
|
+
- a published or locally built `libravdbd` daemon for integration tests
|
|
12
|
+
|
|
13
|
+
Go is only required when building the daemon from a local daemon checkout or
|
|
14
|
+
regenerating Go gRPC stubs.
|
|
15
|
+
|
|
16
|
+
## Source Setup
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm install
|
|
20
|
+
pnpm check
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`pnpm check` runs TypeScript validation and unit tests:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
tsc --noEmit
|
|
27
|
+
tsc -p tsconfig.tests.json && node --test .ts-build/test/unit/*.test.js
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Local Daemon Build
|
|
31
|
+
|
|
32
|
+
Prepare `.daemon-bin/libravdbd` for local plugin testing:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bash scripts/build-daemon.sh
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Supported inputs:
|
|
39
|
+
|
|
40
|
+
- installed daemon on `PATH`, such as `brew install libravdbd`
|
|
41
|
+
- `LIBRAVDBD_BINARY_PATH=/path/to/libravdbd`
|
|
42
|
+
- `LIBRAVDBD_SOURCE_DIR=/path/to/libravdbd` to build from a local daemon repo
|
|
43
|
+
|
|
44
|
+
For daemon-internal Go development and release work, use the separate
|
|
45
|
+
`libravdbd` repository.
|
|
46
|
+
|
|
47
|
+
## Validation Commands
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm check
|
|
51
|
+
npm run test:integration
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Benchmark and tuning commands are documented in
|
|
55
|
+
[Performance and tuning](./performance-and-tuning.md).
|
|
56
|
+
|
|
57
|
+
## Generated IPC Files
|
|
58
|
+
|
|
59
|
+
The plugin imports generated IPC envelope and RPC payload classes from
|
|
60
|
+
`src/generated/libravdb/ipc/v1/rpc_pb.js`.
|
|
61
|
+
|
|
62
|
+
Those generated files are checked in and copied into `dist/generated/` during
|
|
63
|
+
`npm run build`:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm run build
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Do not replace those imports with the older external
|
|
70
|
+
`@xdarkicex/libravdb-contracts` path. The current package resolves generated
|
|
71
|
+
types from this repository.
|
|
72
|
+
|
|
73
|
+
## Proto Generation
|
|
74
|
+
|
|
75
|
+
The repo also contains `api/proto/intelligence_kernel/v1/kernel.proto` and a
|
|
76
|
+
small `Makefile` target for Go gRPC stub generation:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
make proto
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
That target assumes Homebrew-style locations for `go`, `protoc`, and the Go
|
|
83
|
+
plugins. Adjust the Makefile locally if your toolchain lives elsewhere.
|
|
84
|
+
|
|
85
|
+
## Release Shape
|
|
86
|
+
|
|
87
|
+
The npm package contains:
|
|
88
|
+
|
|
89
|
+
- `README.md`
|
|
90
|
+
- `HOOK.md`
|
|
91
|
+
- `index.js`
|
|
92
|
+
- `openclaw.plugin.json`
|
|
93
|
+
- `package.json`
|
|
94
|
+
- `docs/`
|
|
95
|
+
- `dist/`
|
|
96
|
+
|
|
97
|
+
The package is connect-only. It does not compile Go code, download models, or
|
|
98
|
+
manage the daemon process during plugin installation.
|