@xdarkicex/openclaw-memory-libravdb 1.8.6 → 1.8.8
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 +14 -3
- package/dist/context-engine.js +50 -1
- package/dist/index.js +46 -4
- package/dist/tools/memory-recall.d.ts +1 -1
- package/dist/tools/memory-recall.js +2 -2
- package/docs/yaml/default-gguf.yaml +52 -0
- package/docs/yaml/default-onnx.yaml +47 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -318,12 +318,22 @@ libravdbd migrate --from ~/.libravdbd/data.libravdb --tenant <tenantId>
|
|
|
318
318
|
|
|
319
319
|
## Vector Service Configuration (YAML) & Kubernetes
|
|
320
320
|
|
|
321
|
-
`libravdbd` is
|
|
322
|
-
|
|
321
|
+
`libravdbd` is configured via environment variables or a YAML configuration file. The vector service looks for a config file in this order:
|
|
322
|
+
|
|
323
|
+
1. `LIBRAVDB_CONFIG=/path/to/config.yaml` (env var — set this for custom paths)
|
|
323
324
|
2. `/etc/libravdbd/config.yaml`
|
|
324
325
|
3. `~/.libravdbd/config.yaml`
|
|
325
326
|
|
|
326
|
-
|
|
327
|
+
Env vars override YAML values. All fields are optional — the daemon ships with sensible defaults.
|
|
328
|
+
|
|
329
|
+
**Reference YAML files:**
|
|
330
|
+
|
|
331
|
+
| Backend | File | Description |
|
|
332
|
+
|---------|------|-------------|
|
|
333
|
+
| GGUF (recommended) | [`docs/yaml/default-gguf.yaml`](docs/yaml/default-gguf.yaml) | llama.cpp backend, 3-5x faster on CPU |
|
|
334
|
+
| ONNX (fallback) | [`docs/yaml/default-onnx.yaml`](docs/yaml/default-onnx.yaml) | ONNX Runtime backend, wider platform support |
|
|
335
|
+
|
|
336
|
+
**Kubernetes example** (multi-tenant mode with GGUF):
|
|
327
337
|
|
|
328
338
|
```yaml
|
|
329
339
|
# /etc/libravdbd/config.yaml
|
|
@@ -333,6 +343,7 @@ tenant_max_open: 128
|
|
|
333
343
|
grpc_endpoint: "tcp:0.0.0.0:9090"
|
|
334
344
|
embedding_backend: "gguf"
|
|
335
345
|
embedding_profile: "nomic-embed-text-v1.5"
|
|
346
|
+
llama_lib_path: "/var/lib/libravdbd/models/llama/llama-linux-amd64/lib/libllama.so"
|
|
336
347
|
drain_timeout: "25s" # Must be less than k8s terminationGracePeriodSeconds
|
|
337
348
|
```
|
|
338
349
|
|
package/dist/context-engine.js
CHANGED
|
@@ -1626,6 +1626,44 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
|
|
|
1626
1626
|
: {}),
|
|
1627
1627
|
};
|
|
1628
1628
|
}
|
|
1629
|
+
async function injectContinuityContext(params) {
|
|
1630
|
+
try {
|
|
1631
|
+
// Use a natural-language query that semantically matches the
|
|
1632
|
+
// pointer record text ("Previous session continuity — ...").
|
|
1633
|
+
// Fetch enough results so the exact ID match isn't crowded out
|
|
1634
|
+
// by stronger semantic hits in the user collection.
|
|
1635
|
+
const continuityHits = await params.client.searchTextCollections({
|
|
1636
|
+
collections: [resolveUserCollection(params.userId)],
|
|
1637
|
+
text: "previous session context continuity",
|
|
1638
|
+
k: 8,
|
|
1639
|
+
excludeByCollection: {},
|
|
1640
|
+
});
|
|
1641
|
+
const continuityHit = continuityHits.results?.find((r) => r.id === "__session_continuity__");
|
|
1642
|
+
if (!continuityHit)
|
|
1643
|
+
return null;
|
|
1644
|
+
let meta = {};
|
|
1645
|
+
if (continuityHit.metadataJson && continuityHit.metadataJson.length > 0) {
|
|
1646
|
+
try {
|
|
1647
|
+
meta = JSON.parse(new TextDecoder().decode(continuityHit.metadataJson));
|
|
1648
|
+
}
|
|
1649
|
+
catch { /* metadata parse failed, use empty */ }
|
|
1650
|
+
}
|
|
1651
|
+
const summaryId = meta.summary_id;
|
|
1652
|
+
if (!summaryId)
|
|
1653
|
+
return null;
|
|
1654
|
+
const expanded = await params.client.expandSummary({
|
|
1655
|
+
sessionId: meta.session_id ?? params.sessionId,
|
|
1656
|
+
summaryId,
|
|
1657
|
+
maxDepth: 2,
|
|
1658
|
+
});
|
|
1659
|
+
if (!expanded.text)
|
|
1660
|
+
return null;
|
|
1661
|
+
return '<continuity_context>\nThe following is a summary of the previous session. Use it for context about what was discussed before the reset.\n' + expanded.text + '\n</continuity_context>';
|
|
1662
|
+
}
|
|
1663
|
+
catch {
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1629
1667
|
async function runCompaction(args) {
|
|
1630
1668
|
const request = buildCompactSessionRequest(args);
|
|
1631
1669
|
try {
|
|
@@ -1857,7 +1895,18 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
|
|
|
1857
1895
|
emitDebug: true,
|
|
1858
1896
|
});
|
|
1859
1897
|
const assembled = normalizeAssembleResult(resp, args.messages);
|
|
1860
|
-
|
|
1898
|
+
const continuityContext = await injectContinuityContext({
|
|
1899
|
+
client,
|
|
1900
|
+
userId,
|
|
1901
|
+
sessionId,
|
|
1902
|
+
logger,
|
|
1903
|
+
tokenBudget: args.tokenBudget,
|
|
1904
|
+
systemPromptAddition: assembled.systemPromptAddition,
|
|
1905
|
+
});
|
|
1906
|
+
const withContinuity = continuityContext
|
|
1907
|
+
? { ...assembled, systemPromptAddition: appendSystemPromptAddition(assembled.systemPromptAddition, continuityContext) }
|
|
1908
|
+
: assembled;
|
|
1909
|
+
let enforced = enforceTokenBudgetInvariant(await augmentWithExactRecall(withContinuity, {
|
|
1861
1910
|
queryText: strippedPrompt || (messages[messages.length - 1]?.content ?? ""),
|
|
1862
1911
|
userId,
|
|
1863
1912
|
sessionId,
|
package/dist/index.js
CHANGED
|
@@ -28144,6 +28144,38 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
|
|
|
28144
28144
|
...typeof cfg.continuityPriorContextTokens === "number" ? { continuityPriorContextTokens: cfg.continuityPriorContextTokens } : {}
|
|
28145
28145
|
};
|
|
28146
28146
|
}
|
|
28147
|
+
async function injectContinuityContext(params) {
|
|
28148
|
+
try {
|
|
28149
|
+
const continuityHits = await params.client.searchTextCollections({
|
|
28150
|
+
collections: [resolveUserCollection(params.userId)],
|
|
28151
|
+
text: "previous session context continuity",
|
|
28152
|
+
k: 8,
|
|
28153
|
+
excludeByCollection: {}
|
|
28154
|
+
});
|
|
28155
|
+
const continuityHit = continuityHits.results?.find(
|
|
28156
|
+
(r) => r.id === "__session_continuity__"
|
|
28157
|
+
);
|
|
28158
|
+
if (!continuityHit) return null;
|
|
28159
|
+
let meta = {};
|
|
28160
|
+
if (continuityHit.metadataJson && continuityHit.metadataJson.length > 0) {
|
|
28161
|
+
try {
|
|
28162
|
+
meta = JSON.parse(new TextDecoder().decode(continuityHit.metadataJson));
|
|
28163
|
+
} catch {
|
|
28164
|
+
}
|
|
28165
|
+
}
|
|
28166
|
+
const summaryId = meta.summary_id;
|
|
28167
|
+
if (!summaryId) return null;
|
|
28168
|
+
const expanded = await params.client.expandSummary({
|
|
28169
|
+
sessionId: meta.session_id ?? params.sessionId,
|
|
28170
|
+
summaryId,
|
|
28171
|
+
maxDepth: 2
|
|
28172
|
+
});
|
|
28173
|
+
if (!expanded.text) return null;
|
|
28174
|
+
return "<continuity_context>\nThe following is a summary of the previous session. Use it for context about what was discussed before the reset.\n" + expanded.text + "\n</continuity_context>";
|
|
28175
|
+
} catch {
|
|
28176
|
+
return null;
|
|
28177
|
+
}
|
|
28178
|
+
}
|
|
28147
28179
|
async function runCompaction(args) {
|
|
28148
28180
|
const request3 = buildCompactSessionRequest(args);
|
|
28149
28181
|
try {
|
|
@@ -28376,8 +28408,17 @@ function buildContextEngineFactory(runtime, cfg, logger = console) {
|
|
|
28376
28408
|
emitDebug: true
|
|
28377
28409
|
});
|
|
28378
28410
|
const assembled = normalizeAssembleResult(resp, args.messages);
|
|
28411
|
+
const continuityContext = await injectContinuityContext({
|
|
28412
|
+
client,
|
|
28413
|
+
userId,
|
|
28414
|
+
sessionId,
|
|
28415
|
+
logger,
|
|
28416
|
+
tokenBudget: args.tokenBudget,
|
|
28417
|
+
systemPromptAddition: assembled.systemPromptAddition
|
|
28418
|
+
});
|
|
28419
|
+
const withContinuity = continuityContext ? { ...assembled, systemPromptAddition: appendSystemPromptAddition(assembled.systemPromptAddition, continuityContext) } : assembled;
|
|
28379
28420
|
let enforced = enforceTokenBudgetInvariant(
|
|
28380
|
-
await augmentWithExactRecall(
|
|
28421
|
+
await augmentWithExactRecall(withContinuity, {
|
|
28381
28422
|
queryText: strippedPrompt || (messages[messages.length - 1]?.content ?? ""),
|
|
28382
28423
|
userId,
|
|
28383
28424
|
sessionId,
|
|
@@ -36079,7 +36120,7 @@ function createMemoryDescribeTool(getClient, getSessionId = () => void 0, logger
|
|
|
36079
36120
|
}
|
|
36080
36121
|
};
|
|
36081
36122
|
}
|
|
36082
|
-
function createMemoryExpandTool(getClient, getSessionKey, logger = console) {
|
|
36123
|
+
function createMemoryExpandTool(getClient, getSessionKey, logger = console, getSessionId = () => void 0) {
|
|
36083
36124
|
return {
|
|
36084
36125
|
name: "memory_expand",
|
|
36085
36126
|
label: "Memory Expand",
|
|
@@ -36092,7 +36133,7 @@ function createMemoryExpandTool(getClient, getSessionKey, logger = console) {
|
|
|
36092
36133
|
if (summaryIds.length === 0) throw new Error("memory_expand requires at least one summaryId");
|
|
36093
36134
|
const maxDepth = readNum(params, "maxDepth", { integer: true, min: 0 }) ?? 1;
|
|
36094
36135
|
let maxTokens = readNum(params, "maxTokens", { integer: true }) ?? MAX_EXPAND_TOKENS;
|
|
36095
|
-
const sessionId = readStr(params, "sessionId") ?? "";
|
|
36136
|
+
const sessionId = readStr(params, "sessionId") ?? getSessionId() ?? "";
|
|
36096
36137
|
const sessionKey = getSessionKey();
|
|
36097
36138
|
if (sessionKey) {
|
|
36098
36139
|
const grantedTokens = consumeSubagentBudget(sessionKey, maxTokens);
|
|
@@ -39976,7 +40017,8 @@ function register(api) {
|
|
|
39976
40017
|
api.registerTool?.((ctx) => {
|
|
39977
40018
|
const getClient = runtimeOrNull.getClient;
|
|
39978
40019
|
const getSessionKey = () => ctx.sessionKey;
|
|
39979
|
-
|
|
40020
|
+
const getSessionId = () => ctx.sessionId;
|
|
40021
|
+
return createMemoryExpandTool(getClient, getSessionKey, logger, getSessionId);
|
|
39980
40022
|
}, { names: ["memory_expand"] });
|
|
39981
40023
|
api.registerTool?.((ctx) => {
|
|
39982
40024
|
const getClient = runtimeOrNull.getClient;
|
|
@@ -67,7 +67,7 @@ export declare function createMemoryDescribeTool(getClient: ClientGetter, getSes
|
|
|
67
67
|
};
|
|
68
68
|
execute: (_toolCallId: string, rawParams: unknown) => Promise<ToolResult<MemoryDescribeDetails>>;
|
|
69
69
|
};
|
|
70
|
-
export declare function createMemoryExpandTool(getClient: ClientGetter, getSessionKey: () => string | undefined, logger?: LoggerLike): {
|
|
70
|
+
export declare function createMemoryExpandTool(getClient: ClientGetter, getSessionKey: () => string | undefined, logger?: LoggerLike, getSessionId?: () => string | undefined): {
|
|
71
71
|
name: string;
|
|
72
72
|
label: string;
|
|
73
73
|
description: string;
|
|
@@ -187,7 +187,7 @@ export function createMemoryDescribeTool(getClient, getSessionId = () => undefin
|
|
|
187
187
|
},
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
|
-
export function createMemoryExpandTool(getClient, getSessionKey, logger = console) {
|
|
190
|
+
export function createMemoryExpandTool(getClient, getSessionKey, logger = console, getSessionId = () => undefined) {
|
|
191
191
|
return {
|
|
192
192
|
name: "memory_expand",
|
|
193
193
|
label: "Memory Expand",
|
|
@@ -204,7 +204,7 @@ export function createMemoryExpandTool(getClient, getSessionKey, logger = consol
|
|
|
204
204
|
throw new Error("memory_expand requires at least one summaryId");
|
|
205
205
|
const maxDepth = readNum(params, "maxDepth", { integer: true, min: 0 }) ?? 1;
|
|
206
206
|
let maxTokens = readNum(params, "maxTokens", { integer: true }) ?? MAX_EXPAND_TOKENS;
|
|
207
|
-
const sessionId = readStr(params, "sessionId") ?? "";
|
|
207
|
+
const sessionId = readStr(params, "sessionId") ?? getSessionId() ?? "";
|
|
208
208
|
// Subagent budget gate: if this is a subagent, check remaining expansion budget.
|
|
209
209
|
const sessionKey = getSessionKey();
|
|
210
210
|
if (sessionKey) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Vector Service — GGUF backend (recommended)
|
|
2
|
+
#
|
|
3
|
+
# Place at /etc/libravdbd/config.yaml, ~/.libravdbd/config.yaml,
|
|
4
|
+
# or any path pointed to by LIBRAVDB_CONFIG.
|
|
5
|
+
#
|
|
6
|
+
# GGUF/llama.cpp is 3-5x faster than ONNX on CPU.
|
|
7
|
+
# Requires libllama.dylib/.so and a .gguf model file.
|
|
8
|
+
# Provision: scripts/provision.sh (shipped with the daemon release).
|
|
9
|
+
#
|
|
10
|
+
# All fields are optional. Env vars override YAML values.
|
|
11
|
+
|
|
12
|
+
# --- storage ---
|
|
13
|
+
db_path: ""
|
|
14
|
+
|
|
15
|
+
# --- transport ---
|
|
16
|
+
grpc_endpoint: "" # unix:/path/to/sock or tcp:host:port
|
|
17
|
+
|
|
18
|
+
# --- embedding ---
|
|
19
|
+
embedding_backend: gguf # gguf only — does not fall back to ONNX
|
|
20
|
+
embedding_profile: nomic-embed-text-v1.5
|
|
21
|
+
fallback_profile: bge-small-en-v1.5
|
|
22
|
+
embedding_normalize: true
|
|
23
|
+
embedding_dimensions: 768
|
|
24
|
+
|
|
25
|
+
# --- gguf ---
|
|
26
|
+
llama_lib_path: "" # path to libllama.dylib/.so (empty = auto-resolve)
|
|
27
|
+
# Linux example: /var/lib/libravdbd/models/llama/llama-linux-amd64/lib/libllama.so
|
|
28
|
+
# macOS example: /opt/homebrew/opt/libravdbd/models/llama/llama-darwin-arm64/lib/libllama.dylib
|
|
29
|
+
|
|
30
|
+
# --- summarizer ---
|
|
31
|
+
summarizer_backend: bundled # bundled (=extractive, always used regardless)
|
|
32
|
+
|
|
33
|
+
# --- gating ---
|
|
34
|
+
gating_threshold: 0.35
|
|
35
|
+
gating_w1c: 0.35
|
|
36
|
+
gating_w2c: 0.40
|
|
37
|
+
gating_w3c: 0.25
|
|
38
|
+
gating_w1t: 0.40
|
|
39
|
+
gating_w2t: 0.35
|
|
40
|
+
gating_w3t: 0.25
|
|
41
|
+
gating_tech_norm: 1.5
|
|
42
|
+
|
|
43
|
+
# --- timeouts ---
|
|
44
|
+
embed_timeout: 5s
|
|
45
|
+
drain_timeout: 25s
|
|
46
|
+
|
|
47
|
+
# --- circuit breaker ---
|
|
48
|
+
circuit_max_failures: 3
|
|
49
|
+
circuit_cooldown: 60s
|
|
50
|
+
|
|
51
|
+
# --- lifecycle ---
|
|
52
|
+
lifecycle_journal_max_entries: 500
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Vector Service — ONNX backend (default fallback)
|
|
2
|
+
#
|
|
3
|
+
# Place at /etc/libravdbd/config.yaml, ~/.libravdbd/config.yaml,
|
|
4
|
+
# or any path pointed to by LIBRAVDB_CONFIG.
|
|
5
|
+
#
|
|
6
|
+
# All fields are optional. Env vars override YAML values.
|
|
7
|
+
|
|
8
|
+
# --- storage ---
|
|
9
|
+
db_path: ""
|
|
10
|
+
|
|
11
|
+
# --- transport ---
|
|
12
|
+
grpc_endpoint: "" # unix:/path/to/sock or tcp:host:port
|
|
13
|
+
|
|
14
|
+
# --- embedding ---
|
|
15
|
+
embedding_backend: bundled # bundled (=gguf-first, onnx fallback), onnx-local, gguf, remote
|
|
16
|
+
embedding_profile: nomic-embed-text-v1.5
|
|
17
|
+
fallback_profile: bge-small-en-v1.5
|
|
18
|
+
embedding_model_path: ""
|
|
19
|
+
embedding_tokenizer_path: ""
|
|
20
|
+
embedding_dimensions: 768
|
|
21
|
+
embedding_normalize: true
|
|
22
|
+
onnx_runtime_path: "" # path to libonnxruntime.dylib/.so (empty = auto-resolve)
|
|
23
|
+
onnx_device: "" # auto, cpu, cuda, coreml, openvino, directml
|
|
24
|
+
|
|
25
|
+
# --- summarizer ---
|
|
26
|
+
summarizer_backend: bundled # bundled (=extractive, always used regardless)
|
|
27
|
+
|
|
28
|
+
# --- gating ---
|
|
29
|
+
gating_threshold: 0.35
|
|
30
|
+
gating_w1c: 0.35
|
|
31
|
+
gating_w2c: 0.40
|
|
32
|
+
gating_w3c: 0.25
|
|
33
|
+
gating_w1t: 0.40
|
|
34
|
+
gating_w2t: 0.35
|
|
35
|
+
gating_w3t: 0.25
|
|
36
|
+
gating_tech_norm: 1.5
|
|
37
|
+
|
|
38
|
+
# --- timeouts ---
|
|
39
|
+
embed_timeout: 5s
|
|
40
|
+
drain_timeout: 25s
|
|
41
|
+
|
|
42
|
+
# --- circuit breaker ---
|
|
43
|
+
circuit_max_failures: 3
|
|
44
|
+
circuit_cooldown: 60s
|
|
45
|
+
|
|
46
|
+
# --- lifecycle ---
|
|
47
|
+
lifecycle_journal_max_entries: 500
|
package/openclaw.plugin.json
CHANGED