@xdarkicex/openclaw-memory-libravdb 1.6.20 → 1.6.21
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 +4 -1
- package/dist/index.js +116 -62
- package/dist/plugin-runtime.d.ts +1 -0
- package/dist/plugin-runtime.js +55 -1
- package/dist/types.d.ts +4 -0
- package/docs/configuration.md +3 -3
- package/docs/install.md +66 -7
- package/docs/installation.md +77 -9
- package/openclaw.plugin.json +40 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,8 @@ Then activate the plugin in `~/.openclaw/openclaw.json`:
|
|
|
75
75
|
{
|
|
76
76
|
"plugins": {
|
|
77
77
|
"slots": {
|
|
78
|
-
"memory": "libravdb-memory"
|
|
78
|
+
"memory": "libravdb-memory",
|
|
79
|
+
"contextEngine": "libravdb-memory"
|
|
79
80
|
},
|
|
80
81
|
"entries": {
|
|
81
82
|
"libravdb-memory": {
|
|
@@ -185,6 +186,8 @@ All keys are optional. For the full reference, see [Configuration](./docs/config
|
|
|
185
186
|
| `sidecarPath` | string | `auto` | `"auto"` probes standard paths; set `unix:/path` or `tcp:host:port` to override |
|
|
186
187
|
| `embeddingProfile` | string | `nomic-embed-text-v1.5` | Primary embedding model |
|
|
187
188
|
| `fallbackProfile` | string | `bge-small-en-v1.5` | Fallback profile for dimension mismatches |
|
|
189
|
+
| `embeddingRuntimePath` | string | — | Required with `embeddingBackend: "onnx-local"`; path to `libonnxruntime` visible to `libravdbd` |
|
|
190
|
+
| `embeddingModelPath` | string | — | Required with `embeddingBackend: "onnx-local"`; directory containing `embedding.json`, `model.onnx`, and `tokenizer.json` |
|
|
188
191
|
| `onnxDevice` | string | `auto` | ONNX execution provider; set `cpu` to bypass CoreML/MPS on Intel Macs |
|
|
189
192
|
| `userId` | string | auto-derived | Stable identity for cross-session durable memory |
|
|
190
193
|
| `crossSessionRecall` | boolean | `true` | When `false`, only session-scoped memories are retrieved |
|
package/dist/index.js
CHANGED
|
@@ -5162,7 +5162,7 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5162
5162
|
return `enum ${this.typeName}`;
|
|
5163
5163
|
},
|
|
5164
5164
|
getComments() {
|
|
5165
|
-
const
|
|
5165
|
+
const path5 = this.parent ? [
|
|
5166
5166
|
...this.parent.getComments().sourcePath,
|
|
5167
5167
|
FieldNumber.DescriptorProto_EnumType,
|
|
5168
5168
|
this.parent.proto.enumType.indexOf(this.proto)
|
|
@@ -5170,7 +5170,7 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5170
5170
|
FieldNumber.FileDescriptorProto_EnumType,
|
|
5171
5171
|
this.file.proto.enumType.indexOf(this.proto)
|
|
5172
5172
|
];
|
|
5173
|
-
return findComments(file.proto.sourceCodeInfo,
|
|
5173
|
+
return findComments(file.proto.sourceCodeInfo, path5);
|
|
5174
5174
|
},
|
|
5175
5175
|
getFeatures() {
|
|
5176
5176
|
var _a2, _b2;
|
|
@@ -5201,12 +5201,12 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5201
5201
|
return str;
|
|
5202
5202
|
},
|
|
5203
5203
|
getComments() {
|
|
5204
|
-
const
|
|
5204
|
+
const path5 = [
|
|
5205
5205
|
...this.parent.getComments().sourcePath,
|
|
5206
5206
|
FieldNumber.EnumDescriptorProto_Value,
|
|
5207
5207
|
this.parent.proto.value.indexOf(this.proto)
|
|
5208
5208
|
];
|
|
5209
|
-
return findComments(file.proto.sourceCodeInfo,
|
|
5209
|
+
return findComments(file.proto.sourceCodeInfo, path5);
|
|
5210
5210
|
},
|
|
5211
5211
|
getFeatures() {
|
|
5212
5212
|
var _a3;
|
|
@@ -5237,7 +5237,7 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5237
5237
|
return `message ${this.typeName}`;
|
|
5238
5238
|
},
|
|
5239
5239
|
getComments() {
|
|
5240
|
-
const
|
|
5240
|
+
const path5 = this.parent ? [
|
|
5241
5241
|
...this.parent.getComments().sourcePath,
|
|
5242
5242
|
FieldNumber.DescriptorProto_NestedType,
|
|
5243
5243
|
this.parent.proto.nestedType.indexOf(this.proto)
|
|
@@ -5245,7 +5245,7 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5245
5245
|
FieldNumber.FileDescriptorProto_MessageType,
|
|
5246
5246
|
this.file.proto.messageType.indexOf(this.proto)
|
|
5247
5247
|
];
|
|
5248
|
-
return findComments(file.proto.sourceCodeInfo,
|
|
5248
|
+
return findComments(file.proto.sourceCodeInfo, path5);
|
|
5249
5249
|
},
|
|
5250
5250
|
getFeatures() {
|
|
5251
5251
|
var _a2, _b2;
|
|
@@ -5280,11 +5280,11 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5280
5280
|
return `service ${this.typeName}`;
|
|
5281
5281
|
},
|
|
5282
5282
|
getComments() {
|
|
5283
|
-
const
|
|
5283
|
+
const path5 = [
|
|
5284
5284
|
FieldNumber.FileDescriptorProto_Service,
|
|
5285
5285
|
this.file.proto.service.indexOf(this.proto)
|
|
5286
5286
|
];
|
|
5287
|
-
return findComments(file.proto.sourceCodeInfo,
|
|
5287
|
+
return findComments(file.proto.sourceCodeInfo, path5);
|
|
5288
5288
|
},
|
|
5289
5289
|
getFeatures() {
|
|
5290
5290
|
var _a2;
|
|
@@ -5344,12 +5344,12 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5344
5344
|
return `rpc ${parent.typeName}.${name}`;
|
|
5345
5345
|
},
|
|
5346
5346
|
getComments() {
|
|
5347
|
-
const
|
|
5347
|
+
const path5 = [
|
|
5348
5348
|
...this.parent.getComments().sourcePath,
|
|
5349
5349
|
FieldNumber.ServiceDescriptorProto_Method,
|
|
5350
5350
|
this.parent.proto.method.indexOf(this.proto)
|
|
5351
5351
|
];
|
|
5352
|
-
return findComments(parent.file.proto.sourceCodeInfo,
|
|
5352
|
+
return findComments(parent.file.proto.sourceCodeInfo, path5);
|
|
5353
5353
|
},
|
|
5354
5354
|
getFeatures() {
|
|
5355
5355
|
var _a2;
|
|
@@ -5370,12 +5370,12 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5370
5370
|
return `oneof ${parent.typeName}.${this.name}`;
|
|
5371
5371
|
},
|
|
5372
5372
|
getComments() {
|
|
5373
|
-
const
|
|
5373
|
+
const path5 = [
|
|
5374
5374
|
...this.parent.getComments().sourcePath,
|
|
5375
5375
|
FieldNumber.DescriptorProto_OneofDecl,
|
|
5376
5376
|
this.parent.proto.oneofDecl.indexOf(this.proto)
|
|
5377
5377
|
];
|
|
5378
|
-
return findComments(parent.file.proto.sourceCodeInfo,
|
|
5378
|
+
return findComments(parent.file.proto.sourceCodeInfo, path5);
|
|
5379
5379
|
},
|
|
5380
5380
|
getFeatures() {
|
|
5381
5381
|
var _a;
|
|
@@ -5411,12 +5411,12 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5411
5411
|
return `field ${this.parent.typeName}.${this.name}`;
|
|
5412
5412
|
},
|
|
5413
5413
|
getComments() {
|
|
5414
|
-
const
|
|
5414
|
+
const path5 = [
|
|
5415
5415
|
...this.parent.getComments().sourcePath,
|
|
5416
5416
|
FieldNumber.DescriptorProto_Field,
|
|
5417
5417
|
this.parent.proto.field.indexOf(this.proto)
|
|
5418
5418
|
];
|
|
5419
|
-
return findComments(file.proto.sourceCodeInfo,
|
|
5419
|
+
return findComments(file.proto.sourceCodeInfo, path5);
|
|
5420
5420
|
},
|
|
5421
5421
|
getFeatures() {
|
|
5422
5422
|
var _a2;
|
|
@@ -5493,7 +5493,7 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5493
5493
|
return `extension ${this.typeName}`;
|
|
5494
5494
|
},
|
|
5495
5495
|
getComments() {
|
|
5496
|
-
const
|
|
5496
|
+
const path5 = this.parent ? [
|
|
5497
5497
|
...this.parent.getComments().sourcePath,
|
|
5498
5498
|
FieldNumber.DescriptorProto_Extension,
|
|
5499
5499
|
this.parent.proto.extension.indexOf(proto)
|
|
@@ -5501,7 +5501,7 @@ var require_create_descriptor_set = __commonJS({
|
|
|
5501
5501
|
FieldNumber.FileDescriptorProto_Extension,
|
|
5502
5502
|
this.file.proto.extension.indexOf(proto)
|
|
5503
5503
|
];
|
|
5504
|
-
return findComments(file.proto.sourceCodeInfo,
|
|
5504
|
+
return findComments(file.proto.sourceCodeInfo, path5);
|
|
5505
5505
|
},
|
|
5506
5506
|
getFeatures() {
|
|
5507
5507
|
var _a;
|
|
@@ -8624,14 +8624,14 @@ var require_util = __commonJS({
|
|
|
8624
8624
|
}
|
|
8625
8625
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
8626
8626
|
let origin = url.origin != null ? url.origin : `${url.protocol}//${url.hostname}:${port}`;
|
|
8627
|
-
let
|
|
8627
|
+
let path5 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
8628
8628
|
if (origin.endsWith("/")) {
|
|
8629
8629
|
origin = origin.substring(0, origin.length - 1);
|
|
8630
8630
|
}
|
|
8631
|
-
if (
|
|
8632
|
-
|
|
8631
|
+
if (path5 && !path5.startsWith("/")) {
|
|
8632
|
+
path5 = `/${path5}`;
|
|
8633
8633
|
}
|
|
8634
|
-
url = new URL(origin +
|
|
8634
|
+
url = new URL(origin + path5);
|
|
8635
8635
|
}
|
|
8636
8636
|
return url;
|
|
8637
8637
|
}
|
|
@@ -10245,20 +10245,20 @@ var require_parseParams = __commonJS({
|
|
|
10245
10245
|
var require_basename = __commonJS({
|
|
10246
10246
|
"node_modules/.pnpm/@fastify+busboy@2.1.1/node_modules/@fastify/busboy/lib/utils/basename.js"(exports, module) {
|
|
10247
10247
|
"use strict";
|
|
10248
|
-
module.exports = function basename(
|
|
10249
|
-
if (typeof
|
|
10248
|
+
module.exports = function basename(path5) {
|
|
10249
|
+
if (typeof path5 !== "string") {
|
|
10250
10250
|
return "";
|
|
10251
10251
|
}
|
|
10252
|
-
for (var i =
|
|
10253
|
-
switch (
|
|
10252
|
+
for (var i = path5.length - 1; i >= 0; --i) {
|
|
10253
|
+
switch (path5.charCodeAt(i)) {
|
|
10254
10254
|
case 47:
|
|
10255
10255
|
// '/'
|
|
10256
10256
|
case 92:
|
|
10257
|
-
|
|
10258
|
-
return
|
|
10257
|
+
path5 = path5.slice(i + 1);
|
|
10258
|
+
return path5 === ".." || path5 === "." ? "" : path5;
|
|
10259
10259
|
}
|
|
10260
10260
|
}
|
|
10261
|
-
return
|
|
10261
|
+
return path5 === ".." || path5 === "." ? "" : path5;
|
|
10262
10262
|
};
|
|
10263
10263
|
}
|
|
10264
10264
|
});
|
|
@@ -13288,7 +13288,7 @@ var require_request = __commonJS({
|
|
|
13288
13288
|
}
|
|
13289
13289
|
var Request = class _Request {
|
|
13290
13290
|
constructor(origin, {
|
|
13291
|
-
path:
|
|
13291
|
+
path: path5,
|
|
13292
13292
|
method,
|
|
13293
13293
|
body,
|
|
13294
13294
|
headers,
|
|
@@ -13302,11 +13302,11 @@ var require_request = __commonJS({
|
|
|
13302
13302
|
throwOnError,
|
|
13303
13303
|
expectContinue
|
|
13304
13304
|
}, handler) {
|
|
13305
|
-
if (typeof
|
|
13305
|
+
if (typeof path5 !== "string") {
|
|
13306
13306
|
throw new InvalidArgumentError("path must be a string");
|
|
13307
|
-
} else if (
|
|
13307
|
+
} else if (path5[0] !== "/" && !(path5.startsWith("http://") || path5.startsWith("https://")) && method !== "CONNECT") {
|
|
13308
13308
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
13309
|
-
} else if (invalidPathRegex.exec(
|
|
13309
|
+
} else if (invalidPathRegex.exec(path5) !== null) {
|
|
13310
13310
|
throw new InvalidArgumentError("invalid request path");
|
|
13311
13311
|
}
|
|
13312
13312
|
if (typeof method !== "string") {
|
|
@@ -13369,7 +13369,7 @@ var require_request = __commonJS({
|
|
|
13369
13369
|
this.completed = false;
|
|
13370
13370
|
this.aborted = false;
|
|
13371
13371
|
this.upgrade = upgrade || null;
|
|
13372
|
-
this.path = query ? util.buildURL(
|
|
13372
|
+
this.path = query ? util.buildURL(path5, query) : path5;
|
|
13373
13373
|
this.origin = origin;
|
|
13374
13374
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
13375
13375
|
this.blocking = blocking == null ? false : blocking;
|
|
@@ -14377,9 +14377,9 @@ var require_RedirectHandler = __commonJS({
|
|
|
14377
14377
|
return this.handler.onHeaders(statusCode, headers, resume, statusText);
|
|
14378
14378
|
}
|
|
14379
14379
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
14380
|
-
const
|
|
14380
|
+
const path5 = search ? `${pathname}${search}` : pathname;
|
|
14381
14381
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
14382
|
-
this.opts.path =
|
|
14382
|
+
this.opts.path = path5;
|
|
14383
14383
|
this.opts.origin = origin;
|
|
14384
14384
|
this.opts.maxRedirections = 0;
|
|
14385
14385
|
this.opts.query = null;
|
|
@@ -15619,7 +15619,7 @@ var require_client = __commonJS({
|
|
|
15619
15619
|
writeH2(client, client[kHTTP2Session], request3);
|
|
15620
15620
|
return;
|
|
15621
15621
|
}
|
|
15622
|
-
const { body, method, path:
|
|
15622
|
+
const { body, method, path: path5, host, upgrade, headers, blocking, reset } = request3;
|
|
15623
15623
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
15624
15624
|
if (body && typeof body.read === "function") {
|
|
15625
15625
|
body.read(0);
|
|
@@ -15669,7 +15669,7 @@ var require_client = __commonJS({
|
|
|
15669
15669
|
if (blocking) {
|
|
15670
15670
|
socket[kBlocking] = true;
|
|
15671
15671
|
}
|
|
15672
|
-
let header = `${method} ${
|
|
15672
|
+
let header = `${method} ${path5} HTTP/1.1\r
|
|
15673
15673
|
`;
|
|
15674
15674
|
if (typeof host === "string") {
|
|
15675
15675
|
header += `host: ${host}\r
|
|
@@ -15732,7 +15732,7 @@ upgrade: ${upgrade}\r
|
|
|
15732
15732
|
return true;
|
|
15733
15733
|
}
|
|
15734
15734
|
function writeH2(client, session, request3) {
|
|
15735
|
-
const { body, method, path:
|
|
15735
|
+
const { body, method, path: path5, host, upgrade, expectContinue, signal, headers: reqHeaders } = request3;
|
|
15736
15736
|
let headers;
|
|
15737
15737
|
if (typeof reqHeaders === "string") headers = Request[kHTTP2CopyHeaders](reqHeaders.trim());
|
|
15738
15738
|
else headers = reqHeaders;
|
|
@@ -15775,7 +15775,7 @@ upgrade: ${upgrade}\r
|
|
|
15775
15775
|
});
|
|
15776
15776
|
return true;
|
|
15777
15777
|
}
|
|
15778
|
-
headers[HTTP2_HEADER_PATH] =
|
|
15778
|
+
headers[HTTP2_HEADER_PATH] = path5;
|
|
15779
15779
|
headers[HTTP2_HEADER_SCHEME] = "https";
|
|
15780
15780
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
15781
15781
|
if (body && typeof body.read === "function") {
|
|
@@ -18015,20 +18015,20 @@ var require_mock_utils = __commonJS({
|
|
|
18015
18015
|
}
|
|
18016
18016
|
return true;
|
|
18017
18017
|
}
|
|
18018
|
-
function safeUrl(
|
|
18019
|
-
if (typeof
|
|
18020
|
-
return
|
|
18018
|
+
function safeUrl(path5) {
|
|
18019
|
+
if (typeof path5 !== "string") {
|
|
18020
|
+
return path5;
|
|
18021
18021
|
}
|
|
18022
|
-
const pathSegments =
|
|
18022
|
+
const pathSegments = path5.split("?");
|
|
18023
18023
|
if (pathSegments.length !== 2) {
|
|
18024
|
-
return
|
|
18024
|
+
return path5;
|
|
18025
18025
|
}
|
|
18026
18026
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
18027
18027
|
qp.sort();
|
|
18028
18028
|
return [...pathSegments, qp.toString()].join("?");
|
|
18029
18029
|
}
|
|
18030
|
-
function matchKey(mockDispatch2, { path:
|
|
18031
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
18030
|
+
function matchKey(mockDispatch2, { path: path5, method, body, headers }) {
|
|
18031
|
+
const pathMatch = matchValue(mockDispatch2.path, path5);
|
|
18032
18032
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
18033
18033
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
18034
18034
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -18046,7 +18046,7 @@ var require_mock_utils = __commonJS({
|
|
|
18046
18046
|
function getMockDispatch(mockDispatches, key) {
|
|
18047
18047
|
const basePath = key.query ? buildURL(key.path, key.query) : key.path;
|
|
18048
18048
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
18049
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
18049
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path5 }) => matchValue(safeUrl(path5), resolvedPath));
|
|
18050
18050
|
if (matchedMockDispatches.length === 0) {
|
|
18051
18051
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
18052
18052
|
}
|
|
@@ -18083,9 +18083,9 @@ var require_mock_utils = __commonJS({
|
|
|
18083
18083
|
}
|
|
18084
18084
|
}
|
|
18085
18085
|
function buildKey(opts) {
|
|
18086
|
-
const { path:
|
|
18086
|
+
const { path: path5, method, body, headers, query } = opts;
|
|
18087
18087
|
return {
|
|
18088
|
-
path:
|
|
18088
|
+
path: path5,
|
|
18089
18089
|
method,
|
|
18090
18090
|
body,
|
|
18091
18091
|
headers,
|
|
@@ -18534,10 +18534,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
18534
18534
|
}
|
|
18535
18535
|
format(pendingInterceptors) {
|
|
18536
18536
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
18537
|
-
({ method, path:
|
|
18537
|
+
({ method, path: path5, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
18538
18538
|
Method: method,
|
|
18539
18539
|
Origin: origin,
|
|
18540
|
-
Path:
|
|
18540
|
+
Path: path5,
|
|
18541
18541
|
"Status code": statusCode,
|
|
18542
18542
|
Persistent: persist ? "\u2705" : "\u274C",
|
|
18543
18543
|
Invocations: timesInvoked,
|
|
@@ -23157,8 +23157,8 @@ var require_util6 = __commonJS({
|
|
|
23157
23157
|
}
|
|
23158
23158
|
}
|
|
23159
23159
|
}
|
|
23160
|
-
function validateCookiePath(
|
|
23161
|
-
for (const char of
|
|
23160
|
+
function validateCookiePath(path5) {
|
|
23161
|
+
for (const char of path5) {
|
|
23162
23162
|
const code = char.charCodeAt(0);
|
|
23163
23163
|
if (code < 33 || char === ";") {
|
|
23164
23164
|
throw new Error("Invalid cookie path");
|
|
@@ -24838,11 +24838,11 @@ var require_undici = __commonJS({
|
|
|
24838
24838
|
if (typeof opts.path !== "string") {
|
|
24839
24839
|
throw new InvalidArgumentError("invalid opts.path");
|
|
24840
24840
|
}
|
|
24841
|
-
let
|
|
24841
|
+
let path5 = opts.path;
|
|
24842
24842
|
if (!opts.path.startsWith("/")) {
|
|
24843
|
-
|
|
24843
|
+
path5 = `/${path5}`;
|
|
24844
24844
|
}
|
|
24845
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
24845
|
+
url = new URL(util.parseOrigin(url).origin + path5);
|
|
24846
24846
|
} else {
|
|
24847
24847
|
if (!opts) {
|
|
24848
24848
|
opts = typeof url === "object" ? url : {};
|
|
@@ -25030,7 +25030,7 @@ function deriveIdentityParts() {
|
|
|
25030
25030
|
function deriveAutoId(parts) {
|
|
25031
25031
|
return `${parts.username}@${parts.host}#${parts.homeHash}`;
|
|
25032
25032
|
}
|
|
25033
|
-
function writeIdentityFile(
|
|
25033
|
+
function writeIdentityFile(path5, userId, parts) {
|
|
25034
25034
|
const identity = {
|
|
25035
25035
|
userId,
|
|
25036
25036
|
derivedFrom: {
|
|
@@ -25041,15 +25041,15 @@ function writeIdentityFile(path4, userId, parts) {
|
|
|
25041
25041
|
},
|
|
25042
25042
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
25043
25043
|
};
|
|
25044
|
-
const dir = dirname(
|
|
25044
|
+
const dir = dirname(path5);
|
|
25045
25045
|
mkdirSync(dir, { recursive: true });
|
|
25046
|
-
const tmp = `${
|
|
25046
|
+
const tmp = `${path5}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp`;
|
|
25047
25047
|
writeFileSync(tmp, JSON.stringify(identity, null, 2) + "\n", { mode: 384 });
|
|
25048
|
-
renameSync(tmp,
|
|
25048
|
+
renameSync(tmp, path5);
|
|
25049
25049
|
if (process.platform === "win32") {
|
|
25050
25050
|
try {
|
|
25051
25051
|
execSync(
|
|
25052
|
-
`icacls "${
|
|
25052
|
+
`icacls "${path5}" /inheritance:r /grant:r "%USERNAME%:(R,W)"`,
|
|
25053
25053
|
{ stdio: "ignore", timeout: 5e3 }
|
|
25054
25054
|
);
|
|
25055
25055
|
} catch {
|
|
@@ -35670,11 +35670,11 @@ var Http2SessionManager = class {
|
|
|
35670
35670
|
* Clients must call notifyResponseByteRead() whenever they successfully read
|
|
35671
35671
|
* data from the http2.ClientHttp2Stream.
|
|
35672
35672
|
*/
|
|
35673
|
-
async request(method,
|
|
35673
|
+
async request(method, path5, headers, options) {
|
|
35674
35674
|
for (; ; ) {
|
|
35675
35675
|
const ready2 = await this.gotoReady();
|
|
35676
35676
|
try {
|
|
35677
|
-
const stream = ready2.conn.request(Object.assign(Object.assign({}, headers), { ":method": method, ":path":
|
|
35677
|
+
const stream = ready2.conn.request(Object.assign(Object.assign({}, headers), { ":method": method, ":path": path5 }), options);
|
|
35678
35678
|
ready2.registerRequest(stream);
|
|
35679
35679
|
return stream;
|
|
35680
35680
|
} catch (e) {
|
|
@@ -36983,12 +36983,39 @@ function loadSecretFromEnv(logger) {
|
|
|
36983
36983
|
}
|
|
36984
36984
|
|
|
36985
36985
|
// src/plugin-runtime.ts
|
|
36986
|
+
import { existsSync as existsSync2, statSync } from "node:fs";
|
|
36987
|
+
import path4 from "node:path";
|
|
36986
36988
|
var DEFAULT_RPC_TIMEOUT_MS = 3e4;
|
|
36987
36989
|
var VALID_TLS_MODES = ["auto", "tls", "insecure"];
|
|
36988
36990
|
var isTlsModeValid = (m) => VALID_TLS_MODES.includes(m);
|
|
36989
36991
|
function daemonProvisioningHint() {
|
|
36990
36992
|
return "If you installed the npm package, install and start libravdbd separately; the package does not provision the daemon binary, ONNX Runtime, or model assets.";
|
|
36991
36993
|
}
|
|
36994
|
+
function validateEmbeddingConfig(cfg) {
|
|
36995
|
+
if (cfg.embeddingBackend !== "onnx-local") {
|
|
36996
|
+
return;
|
|
36997
|
+
}
|
|
36998
|
+
const runtimePath = cfg.embeddingRuntimePath?.trim();
|
|
36999
|
+
const modelPath = cfg.embeddingModelPath?.trim();
|
|
37000
|
+
if (!runtimePath || !modelPath) {
|
|
37001
|
+
throw new Error(
|
|
37002
|
+
`LibraVDB: embeddingBackend="onnx-local" requires embeddingRuntimePath and embeddingModelPath. Start libravdbd with matching LIBRAVDB_ONNX_RUNTIME and LIBRAVDB_EMBEDDING_MODEL values.`
|
|
37003
|
+
);
|
|
37004
|
+
}
|
|
37005
|
+
if (!shouldValidateLocalEmbeddingPaths(cfg)) {
|
|
37006
|
+
return;
|
|
37007
|
+
}
|
|
37008
|
+
if (!pathExistsAsFile(runtimePath)) {
|
|
37009
|
+
throw new Error(
|
|
37010
|
+
`LibraVDB: embeddingRuntimePath must point to a readable ONNX Runtime library: ${runtimePath}`
|
|
37011
|
+
);
|
|
37012
|
+
}
|
|
37013
|
+
if (!pathExistsAsDirectory(modelPath) || !pathExistsAsFile(path4.join(modelPath, "embedding.json"))) {
|
|
37014
|
+
throw new Error(
|
|
37015
|
+
`LibraVDB: embeddingModelPath must point to a directory containing embedding.json: ${modelPath}`
|
|
37016
|
+
);
|
|
37017
|
+
}
|
|
37018
|
+
}
|
|
36992
37019
|
function createPluginRuntime(cfg, logger = console) {
|
|
36993
37020
|
let started = null;
|
|
36994
37021
|
let stopped = false;
|
|
@@ -37001,6 +37028,7 @@ function createPluginRuntime(cfg, logger = console) {
|
|
|
37001
37028
|
if (!started) {
|
|
37002
37029
|
let client;
|
|
37003
37030
|
started = (async () => {
|
|
37031
|
+
validateEmbeddingConfig(cfg);
|
|
37004
37032
|
validateTlsConfig(cfg, logger);
|
|
37005
37033
|
client = new LibravDBClient({
|
|
37006
37034
|
endpoint: cfg.grpcEndpoint || cfg.sidecarPath,
|
|
@@ -37070,6 +37098,32 @@ function createPluginRuntime(cfg, logger = console) {
|
|
|
37070
37098
|
}
|
|
37071
37099
|
};
|
|
37072
37100
|
}
|
|
37101
|
+
function shouldValidateLocalEmbeddingPaths(cfg) {
|
|
37102
|
+
const endpoint = resolveClientEndpoint(cfg.grpcEndpoint || cfg.sidecarPath).trim();
|
|
37103
|
+
if (!endpoint || endpoint === "auto" || endpoint.startsWith("unix:")) {
|
|
37104
|
+
return true;
|
|
37105
|
+
}
|
|
37106
|
+
if (!endpoint.startsWith("tcp:")) {
|
|
37107
|
+
return false;
|
|
37108
|
+
}
|
|
37109
|
+
const target = endpoint.slice("tcp:".length);
|
|
37110
|
+
const host = target.startsWith("[") ? target.slice(1, target.indexOf("]")) : target.split(":")[0];
|
|
37111
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1";
|
|
37112
|
+
}
|
|
37113
|
+
function pathExistsAsFile(filePath) {
|
|
37114
|
+
try {
|
|
37115
|
+
return existsSync2(filePath) && statSync(filePath).isFile();
|
|
37116
|
+
} catch {
|
|
37117
|
+
return false;
|
|
37118
|
+
}
|
|
37119
|
+
}
|
|
37120
|
+
function pathExistsAsDirectory(dirPath) {
|
|
37121
|
+
try {
|
|
37122
|
+
return existsSync2(dirPath) && statSync(dirPath).isDirectory();
|
|
37123
|
+
} catch {
|
|
37124
|
+
return false;
|
|
37125
|
+
}
|
|
37126
|
+
}
|
|
37073
37127
|
function validateTlsConfig(cfg, logger) {
|
|
37074
37128
|
if (cfg.grpcEndpointTlsMode !== void 0 && !isTlsModeValid(cfg.grpcEndpointTlsMode)) {
|
|
37075
37129
|
throw new Error(
|
package/dist/plugin-runtime.d.ts
CHANGED
|
@@ -28,5 +28,6 @@ export interface PluginRuntime {
|
|
|
28
28
|
shutdown(): Promise<void>;
|
|
29
29
|
}
|
|
30
30
|
export declare function daemonProvisioningHint(): string;
|
|
31
|
+
export declare function validateEmbeddingConfig(cfg: PluginConfig): void;
|
|
31
32
|
export declare function createPluginRuntime(cfg: PluginConfig, logger?: LoggerLike): PluginRuntime;
|
|
32
33
|
export declare function enrichStartupError(error: unknown, healthMessage?: string): Error;
|
package/dist/plugin-runtime.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { LibravDBClient } from "./libravdb-client.js";
|
|
1
|
+
import { LibravDBClient, resolveClientEndpoint } from "./libravdb-client.js";
|
|
2
2
|
import { formatError } from "./format-error.js";
|
|
3
|
+
import { existsSync, statSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
3
5
|
export const DEFAULT_RPC_TIMEOUT_MS = 30000;
|
|
4
6
|
export const STARTUP_HEALTH_TIMEOUT_MS = 2000;
|
|
5
7
|
export const VALID_TLS_MODES = ["auto", "tls", "insecure"];
|
|
@@ -10,6 +12,26 @@ export function resolveStartupHealthTimeoutMs(cfg) {
|
|
|
10
12
|
export function daemonProvisioningHint() {
|
|
11
13
|
return "If you installed the npm package, install and start libravdbd separately; the package does not provision the daemon binary, ONNX Runtime, or model assets.";
|
|
12
14
|
}
|
|
15
|
+
export function validateEmbeddingConfig(cfg) {
|
|
16
|
+
if (cfg.embeddingBackend !== "onnx-local") {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const runtimePath = cfg.embeddingRuntimePath?.trim();
|
|
20
|
+
const modelPath = cfg.embeddingModelPath?.trim();
|
|
21
|
+
if (!runtimePath || !modelPath) {
|
|
22
|
+
throw new Error(`LibraVDB: embeddingBackend="onnx-local" requires embeddingRuntimePath and embeddingModelPath. ` +
|
|
23
|
+
`Start libravdbd with matching LIBRAVDB_ONNX_RUNTIME and LIBRAVDB_EMBEDDING_MODEL values.`);
|
|
24
|
+
}
|
|
25
|
+
if (!shouldValidateLocalEmbeddingPaths(cfg)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!pathExistsAsFile(runtimePath)) {
|
|
29
|
+
throw new Error(`LibraVDB: embeddingRuntimePath must point to a readable ONNX Runtime library: ${runtimePath}`);
|
|
30
|
+
}
|
|
31
|
+
if (!pathExistsAsDirectory(modelPath) || !pathExistsAsFile(path.join(modelPath, "embedding.json"))) {
|
|
32
|
+
throw new Error(`LibraVDB: embeddingModelPath must point to a directory containing embedding.json: ${modelPath}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
13
35
|
export function createPluginRuntime(cfg, logger = console) {
|
|
14
36
|
let started = null;
|
|
15
37
|
let stopped = false;
|
|
@@ -22,6 +44,7 @@ export function createPluginRuntime(cfg, logger = console) {
|
|
|
22
44
|
if (!started) {
|
|
23
45
|
let client;
|
|
24
46
|
started = (async () => {
|
|
47
|
+
validateEmbeddingConfig(cfg);
|
|
25
48
|
validateTlsConfig(cfg, logger);
|
|
26
49
|
client = new LibravDBClient({
|
|
27
50
|
endpoint: cfg.grpcEndpoint || cfg.sidecarPath,
|
|
@@ -97,6 +120,37 @@ export function createPluginRuntime(cfg, logger = console) {
|
|
|
97
120
|
},
|
|
98
121
|
};
|
|
99
122
|
}
|
|
123
|
+
function shouldValidateLocalEmbeddingPaths(cfg) {
|
|
124
|
+
// Resolve the same endpoint the client will use — respects LIBRAVDB_GRPC_ENDPOINT env var
|
|
125
|
+
const endpoint = resolveClientEndpoint(cfg.grpcEndpoint || cfg.sidecarPath).trim();
|
|
126
|
+
if (!endpoint || endpoint === "auto" || endpoint.startsWith("unix:")) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
if (!endpoint.startsWith("tcp:")) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const target = endpoint.slice("tcp:".length);
|
|
133
|
+
const host = target.startsWith("[")
|
|
134
|
+
? target.slice(1, target.indexOf("]"))
|
|
135
|
+
: target.split(":")[0];
|
|
136
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1";
|
|
137
|
+
}
|
|
138
|
+
function pathExistsAsFile(filePath) {
|
|
139
|
+
try {
|
|
140
|
+
return existsSync(filePath) && statSync(filePath).isFile();
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function pathExistsAsDirectory(dirPath) {
|
|
147
|
+
try {
|
|
148
|
+
return existsSync(dirPath) && statSync(dirPath).isDirectory();
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
100
154
|
function validateTlsConfig(cfg, logger) {
|
|
101
155
|
if (cfg.grpcEndpointTlsMode !== undefined &&
|
|
102
156
|
!isTlsModeValid(cfg.grpcEndpointTlsMode)) {
|
package/dist/types.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface PluginConfig {
|
|
|
15
15
|
crossSessionRecall?: boolean;
|
|
16
16
|
useSessionRecallProjection?: boolean;
|
|
17
17
|
useSessionSummarySearchExperiment?: boolean;
|
|
18
|
+
/** Path to the daemon-visible ONNX Runtime library.
|
|
19
|
+
* Required when embeddingBackend is "onnx-local". */
|
|
18
20
|
embeddingRuntimePath?: string;
|
|
19
21
|
/** Optional ONNX execution provider override passed through to libravdbd.
|
|
20
22
|
* Use "cpu" to bypass CoreML/MPS on Intel Macs or fragile GPU/NPU providers. */
|
|
@@ -22,6 +24,8 @@ export interface PluginConfig {
|
|
|
22
24
|
embeddingBackend?: "bundled" | "onnx-local" | "gguf" | "custom-local" | "remote";
|
|
23
25
|
embeddingProfile?: string;
|
|
24
26
|
fallbackProfile?: string;
|
|
27
|
+
/** Path to a daemon-visible model directory containing embedding.json.
|
|
28
|
+
* Required when embeddingBackend is "onnx-local". */
|
|
25
29
|
embeddingModelPath?: string;
|
|
26
30
|
embeddingTokenizerPath?: string;
|
|
27
31
|
embeddingDimensions?: number;
|
package/docs/configuration.md
CHANGED
|
@@ -87,10 +87,10 @@ address, explicitly set `grpcEndpointTlsMode: "tls"` to match:
|
|
|
87
87
|
|---|---|---|---|
|
|
88
88
|
| `embeddingProfile` | string | `nomic-embed-text-v1.5` | Primary embedding model |
|
|
89
89
|
| `fallbackProfile` | string | `bge-small-en-v1.5` | Fallback when primary model fails dimension checks |
|
|
90
|
-
| `embeddingBackend` | string | — | `bundled`, `onnx-local`,
|
|
90
|
+
| `embeddingBackend` | string | — | `bundled`, `onnx-local`, `custom-local`, or `remote` |
|
|
91
91
|
| `onnxDevice` | string | `auto` | ONNX execution provider: `auto`, `cpu`, `coreml` (macOS), `cuda` (Linux/Windows), `directml` (Windows), `openvino` (Linux) |
|
|
92
|
-
| `embeddingRuntimePath` | string | — | Path to ONNX runtime library (maps to `LIBRAVDB_ONNX_RUNTIME`) |
|
|
93
|
-
| `embeddingModelPath` | string | — | Path to
|
|
92
|
+
| `embeddingRuntimePath` | string | — | Path to ONNX runtime library visible to the daemon (maps to `LIBRAVDB_ONNX_RUNTIME`; required with `embeddingBackend: "onnx-local"`) |
|
|
93
|
+
| `embeddingModelPath` | string | — | Path to the model directory containing `embedding.json`, `model.onnx`, and `tokenizer.json` (maps to `LIBRAVDB_EMBEDDING_MODEL`; required with `embeddingBackend: "onnx-local"`) |
|
|
94
94
|
| `embeddingTokenizerPath` | string | — | Path to custom tokenizer file |
|
|
95
95
|
| `embeddingDimensions` | number | — | Embedding dimension override |
|
|
96
96
|
| `embeddingNormalize` | boolean | — | Enable embedding normalization |
|
package/docs/install.md
CHANGED
|
@@ -37,7 +37,8 @@ openclaw plugins install @xdarkicex/openclaw-memory-libravdb
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
If you use the OpenClaw.ai plugin UI instead of the CLI, install the same
|
|
40
|
-
package and then assign the plugin id `libravdb-memory` to the `memory`
|
|
40
|
+
package and then assign the plugin id `libravdb-memory` to the `memory` and
|
|
41
|
+
`contextEngine` slots.
|
|
41
42
|
|
|
42
43
|
Activate the plugin in `~/.openclaw/openclaw.json`:
|
|
43
44
|
|
|
@@ -45,7 +46,8 @@ Activate the plugin in `~/.openclaw/openclaw.json`:
|
|
|
45
46
|
{
|
|
46
47
|
"plugins": {
|
|
47
48
|
"slots": {
|
|
48
|
-
"memory": "libravdb-memory"
|
|
49
|
+
"memory": "libravdb-memory",
|
|
50
|
+
"contextEngine": "libravdb-memory"
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
}
|
|
@@ -57,7 +59,8 @@ If you run the daemon on a non-default endpoint, add a plugin config:
|
|
|
57
59
|
{
|
|
58
60
|
"plugins": {
|
|
59
61
|
"slots": {
|
|
60
|
-
"memory": "libravdb-memory"
|
|
62
|
+
"memory": "libravdb-memory",
|
|
63
|
+
"contextEngine": "libravdb-memory"
|
|
61
64
|
},
|
|
62
65
|
"entries": {
|
|
63
66
|
"libravdb-memory": {
|
|
@@ -73,7 +76,7 @@ If you run the daemon on a non-default endpoint, add a plugin config:
|
|
|
73
76
|
|
|
74
77
|
When `sidecarPath` is set to `"auto"`, the plugin resolves endpoints in this order on macOS/Linux:
|
|
75
78
|
|
|
76
|
-
1. `
|
|
79
|
+
1. `LIBRAVDB_GRPC_ENDPOINT` if it is set to a valid daemon endpoint
|
|
77
80
|
2. `$HOME/.libravdbd/run/libravdb.sock` if it exists
|
|
78
81
|
3. `/opt/homebrew/var/libravdbd/run/libravdb.sock` if it exists
|
|
79
82
|
4. `/usr/local/var/libravdbd/run/libravdb.sock` if it exists
|
|
@@ -81,7 +84,7 @@ When `sidecarPath` is set to `"auto"`, the plugin resolves endpoints in this ord
|
|
|
81
84
|
|
|
82
85
|
## Sidecar Daemon Install
|
|
83
86
|
|
|
84
|
-
The daemon owns the local database, embeddings, and
|
|
87
|
+
The daemon owns the local database, embeddings, and gRPC endpoint.
|
|
85
88
|
|
|
86
89
|
Default endpoints:
|
|
87
90
|
|
|
@@ -155,12 +158,68 @@ libravdbd serve
|
|
|
155
158
|
That mode is useful for debugging or validating a local release asset before
|
|
156
159
|
you wrap it in `brew services`, `systemd`, or `launchd`.
|
|
157
160
|
|
|
161
|
+
### Containers and Docker
|
|
162
|
+
|
|
163
|
+
The npm plugin does not start `libravdbd`. In a container, either run a separate
|
|
164
|
+
daemon sidecar or use a small entrypoint wrapper that starts the daemon before
|
|
165
|
+
the OpenClaw gateway.
|
|
166
|
+
|
|
167
|
+
Keep the daemon assets and database in a mounted volume and point both the
|
|
168
|
+
daemon and plugin at paths inside the container:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
export LIBRAVDB_GRPC_ENDPOINT=unix:/home/node/.openclaw/libravdbd/run/libravdb.sock
|
|
172
|
+
export LIBRAVDB_DB_PATH=/home/node/.openclaw/libravdbd/data.libravdb
|
|
173
|
+
export LIBRAVDB_ONNX_RUNTIME=/home/node/.openclaw/libravdbd/models/onnxruntime/lib/libonnxruntime.so
|
|
174
|
+
export LIBRAVDB_EMBEDDING_MODEL=/home/node/.openclaw/libravdbd/models/nomic-embed-text-v1.5
|
|
175
|
+
export LIBRAVDB_ONNX_DEVICE=cpu
|
|
176
|
+
libravdbd serve &
|
|
177
|
+
|
|
178
|
+
# Wait for socket to be ready
|
|
179
|
+
for i in {1..30}; do
|
|
180
|
+
[ -S "$LIBRAVDB_GRPC_ENDPOINT" ] && break
|
|
181
|
+
sleep 0.5
|
|
182
|
+
done
|
|
183
|
+
|
|
184
|
+
node dist/index.js gateway --bind lan --port 18789
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Use matching plugin config:
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"plugins": {
|
|
192
|
+
"slots": {
|
|
193
|
+
"memory": "libravdb-memory",
|
|
194
|
+
"contextEngine": "libravdb-memory"
|
|
195
|
+
},
|
|
196
|
+
"entries": {
|
|
197
|
+
"libravdb-memory": {
|
|
198
|
+
"enabled": true,
|
|
199
|
+
"config": {
|
|
200
|
+
"sidecarPath": "unix:/home/node/.openclaw/libravdbd/run/libravdb.sock",
|
|
201
|
+
"embeddingBackend": "onnx-local",
|
|
202
|
+
"embeddingRuntimePath": "/home/node/.openclaw/libravdbd/models/onnxruntime/lib/libonnxruntime.so",
|
|
203
|
+
"embeddingModelPath": "/home/node/.openclaw/libravdbd/models/nomic-embed-text-v1.5",
|
|
204
|
+
"onnxDevice": "cpu"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
For public bots, deny manual memory tools unless users are supposed to query the
|
|
213
|
+
store directly. The context engine can still use LibraVDB for recall while
|
|
214
|
+
`memory_search` and `memory_get` remain unavailable to channel users.
|
|
215
|
+
|
|
158
216
|
## Lifecycle Management
|
|
159
217
|
|
|
160
218
|
### Plugin Lifecycle
|
|
161
219
|
|
|
162
220
|
- Install the package with `openclaw plugins install`.
|
|
163
|
-
- Activate it by assigning `libravdb-memory` to the `memory`
|
|
221
|
+
- Activate it by assigning `libravdb-memory` to the `memory` and
|
|
222
|
+
`contextEngine` slots.
|
|
164
223
|
- Update it with your normal OpenClaw plugin update flow.
|
|
165
224
|
- Disable it by removing the slot assignment from `~/.openclaw/openclaw.json`.
|
|
166
225
|
|
|
@@ -185,7 +244,7 @@ openclaw memory status
|
|
|
185
244
|
Healthy output should show that:
|
|
186
245
|
|
|
187
246
|
- the daemon answered the local health check
|
|
188
|
-
- the memory
|
|
247
|
+
- the memory and context-engine slots are active
|
|
189
248
|
- the plugin can read stored counts and runtime settings
|
|
190
249
|
|
|
191
250
|
If OpenClaw cannot reach the daemon, verify the endpoint first:
|
package/docs/installation.md
CHANGED
|
@@ -60,20 +60,22 @@ or run `libravdbd serve` in a terminal for validation.
|
|
|
60
60
|
|
|
61
61
|
## Activation
|
|
62
62
|
|
|
63
|
-
Assign `libravdb-memory` to the OpenClaw memory
|
|
63
|
+
Assign `libravdb-memory` to the OpenClaw memory and context-engine slots:
|
|
64
64
|
|
|
65
65
|
```json
|
|
66
66
|
{
|
|
67
67
|
"plugins": {
|
|
68
68
|
"slots": {
|
|
69
|
-
"memory": "libravdb-memory"
|
|
69
|
+
"memory": "libravdb-memory",
|
|
70
|
+
"contextEngine": "libravdb-memory"
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
The
|
|
76
|
-
|
|
76
|
+
The memory slot owns `openclaw memory ...` and memory-runtime calls. The
|
|
77
|
+
context-engine slot enables automatic bootstrap, ingest, after-turn, and recall
|
|
78
|
+
hooks during sessions.
|
|
77
79
|
|
|
78
80
|
If the daemon uses a non-default endpoint, add `sidecarPath`:
|
|
79
81
|
|
|
@@ -81,7 +83,8 @@ If the daemon uses a non-default endpoint, add `sidecarPath`:
|
|
|
81
83
|
{
|
|
82
84
|
"plugins": {
|
|
83
85
|
"slots": {
|
|
84
|
-
"memory": "libravdb-memory"
|
|
86
|
+
"memory": "libravdb-memory",
|
|
87
|
+
"contextEngine": "libravdb-memory"
|
|
85
88
|
},
|
|
86
89
|
"entries": {
|
|
87
90
|
"libravdb-memory": {
|
|
@@ -97,7 +100,7 @@ If the daemon uses a non-default endpoint, add `sidecarPath`:
|
|
|
97
100
|
|
|
98
101
|
When `sidecarPath` is `"auto"`, macOS/Linux endpoint resolution checks:
|
|
99
102
|
|
|
100
|
-
1. `
|
|
103
|
+
1. `LIBRAVDB_GRPC_ENDPOINT`
|
|
101
104
|
2. `$HOME/.libravdbd/run/libravdb.sock`
|
|
102
105
|
3. `/opt/homebrew/var/libravdbd/run/libravdb.sock`
|
|
103
106
|
4. `/usr/local/var/libravdbd/run/libravdb.sock`
|
|
@@ -117,6 +120,59 @@ Default data path:
|
|
|
117
120
|
$HOME/.libravdbd/data_nomic-embed-text-v1_5.libravdb
|
|
118
121
|
```
|
|
119
122
|
|
|
123
|
+
## Container Layout
|
|
124
|
+
|
|
125
|
+
In Docker, keep the daemon, model assets, socket, logs, and database in the
|
|
126
|
+
same mounted OpenClaw state volume. A typical container-side layout is:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
/home/node/.openclaw/bin/libravdbd
|
|
130
|
+
/home/node/.openclaw/libravdbd/run/libravdb.sock
|
|
131
|
+
/home/node/.openclaw/libravdbd/data.libravdb
|
|
132
|
+
/home/node/.openclaw/libravdbd/models/onnxruntime/lib/libonnxruntime.so
|
|
133
|
+
/home/node/.openclaw/libravdbd/models/nomic-embed-text-v1.5/embedding.json
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Start the daemon with explicit local ONNX paths before starting the gateway:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
LIBRAVDB_GRPC_ENDPOINT=unix:/home/node/.openclaw/libravdbd/run/libravdb.sock \
|
|
140
|
+
LIBRAVDB_DB_PATH=/home/node/.openclaw/libravdbd/data.libravdb \
|
|
141
|
+
LIBRAVDB_ONNX_RUNTIME=/home/node/.openclaw/libravdbd/models/onnxruntime/lib/libonnxruntime.so \
|
|
142
|
+
LIBRAVDB_EMBEDDING_MODEL=/home/node/.openclaw/libravdbd/models/nomic-embed-text-v1.5 \
|
|
143
|
+
LIBRAVDB_ONNX_DEVICE=cpu \
|
|
144
|
+
/home/node/.openclaw/bin/libravdbd serve
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Then configure the plugin with the same socket and asset paths:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"plugins": {
|
|
152
|
+
"slots": {
|
|
153
|
+
"memory": "libravdb-memory",
|
|
154
|
+
"contextEngine": "libravdb-memory"
|
|
155
|
+
},
|
|
156
|
+
"entries": {
|
|
157
|
+
"libravdb-memory": {
|
|
158
|
+
"enabled": true,
|
|
159
|
+
"config": {
|
|
160
|
+
"sidecarPath": "unix:/home/node/.openclaw/libravdbd/run/libravdb.sock",
|
|
161
|
+
"embeddingBackend": "onnx-local",
|
|
162
|
+
"embeddingRuntimePath": "/home/node/.openclaw/libravdbd/models/onnxruntime/lib/libonnxruntime.so",
|
|
163
|
+
"embeddingModelPath": "/home/node/.openclaw/libravdbd/models/nomic-embed-text-v1.5",
|
|
164
|
+
"onnxDevice": "cpu"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Do not let a container initialize a database with deterministic fallback
|
|
173
|
+
embeddings and later switch the same file to ONNX embeddings. Move the fallback
|
|
174
|
+
database aside first, then let the daemon create a fresh ONNX-backed store.
|
|
175
|
+
|
|
120
176
|
## Verification
|
|
121
177
|
|
|
122
178
|
Run:
|
|
@@ -157,6 +213,8 @@ Common causes:
|
|
|
157
213
|
- `sidecarPath` points at the wrong endpoint
|
|
158
214
|
- ONNX Runtime assets are missing or unpacked in the wrong place
|
|
159
215
|
- a model asset failed checksum validation
|
|
216
|
+
- `embeddingBackend` is set to `onnx-local` but `embeddingRuntimePath` or
|
|
217
|
+
`embeddingModelPath` is missing from plugin config
|
|
160
218
|
|
|
161
219
|
Check the daemon first:
|
|
162
220
|
|
|
@@ -171,6 +229,15 @@ For foreground debugging:
|
|
|
171
229
|
libravdbd serve
|
|
172
230
|
```
|
|
173
231
|
|
|
232
|
+
### Deterministic fallback embeddings
|
|
233
|
+
|
|
234
|
+
If daemon logs mention deterministic fallback mode, the daemon did not find the
|
|
235
|
+
configured ONNX runtime or model manifest. Stop the daemon, set
|
|
236
|
+
`LIBRAVDB_ONNX_RUNTIME` and `LIBRAVDB_EMBEDDING_MODEL`, confirm the model
|
|
237
|
+
directory contains `embedding.json`, then restart. If a database was created
|
|
238
|
+
while fallback mode was active, move that `.libravdb` file and its adjacent
|
|
239
|
+
`.embedding.json` aside before starting with ONNX assets.
|
|
240
|
+
|
|
174
241
|
### Incompatible database or embedding profile
|
|
175
242
|
|
|
176
243
|
If the daemon exits with `database format is incompatible` or `database
|
|
@@ -202,9 +269,10 @@ setup, or republish the release with corrected checksums.
|
|
|
202
269
|
|
|
203
270
|
### Default memory still appears active
|
|
204
271
|
|
|
205
|
-
Confirm that `libravdb-memory` is assigned to `plugins.slots.memory
|
|
206
|
-
Without
|
|
207
|
-
parallel.
|
|
272
|
+
Confirm that `libravdb-memory` is assigned to both `plugins.slots.memory` and
|
|
273
|
+
`plugins.slots.contextEngine`. Without the memory slot, OpenClaw's default
|
|
274
|
+
memory path can continue to run in parallel. Without the context-engine slot,
|
|
275
|
+
automatic session ingest and recall may not run.
|
|
208
276
|
|
|
209
277
|
### Lifecycle journal looks empty
|
|
210
278
|
|
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.6.
|
|
5
|
+
"version": "1.6.21",
|
|
6
6
|
"kind": [
|
|
7
7
|
"memory",
|
|
8
8
|
"context-engine"
|
|
@@ -19,21 +19,43 @@
|
|
|
19
19
|
"configSchema": {
|
|
20
20
|
"type": "object",
|
|
21
21
|
"additionalProperties": false,
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
"
|
|
22
|
+
"allOf": [
|
|
23
|
+
{
|
|
24
|
+
"if": {
|
|
25
|
+
"properties": {
|
|
26
|
+
"embeddingBackend": {
|
|
27
|
+
"const": "remote"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": [
|
|
31
|
+
"embeddingBackend"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"then": {
|
|
35
|
+
"required": [
|
|
36
|
+
"embeddingEndpoint"
|
|
37
|
+
]
|
|
26
38
|
}
|
|
27
39
|
},
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
{
|
|
41
|
+
"if": {
|
|
42
|
+
"properties": {
|
|
43
|
+
"embeddingBackend": {
|
|
44
|
+
"const": "onnx-local"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"required": [
|
|
48
|
+
"embeddingBackend"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"then": {
|
|
52
|
+
"required": [
|
|
53
|
+
"embeddingRuntimePath",
|
|
54
|
+
"embeddingModelPath"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
],
|
|
37
59
|
"properties": {
|
|
38
60
|
"dbPath": {
|
|
39
61
|
"type": "string"
|
|
@@ -137,7 +159,8 @@
|
|
|
137
159
|
"type": "number"
|
|
138
160
|
},
|
|
139
161
|
"embeddingRuntimePath": {
|
|
140
|
-
"type": "string"
|
|
162
|
+
"type": "string",
|
|
163
|
+
"description": "Path to the ONNX Runtime library visible to the daemon, for example /opt/homebrew/opt/libravdbd/models/onnxruntime/lib/libonnxruntime.dylib or /home/node/.openclaw/libravdbd/models/onnxruntime/lib/libonnxruntime.so."
|
|
141
164
|
},
|
|
142
165
|
"onnxDevice": {
|
|
143
166
|
"type": "string",
|
|
@@ -171,7 +194,8 @@
|
|
|
171
194
|
"default": "bge-small-en-v1.5"
|
|
172
195
|
},
|
|
173
196
|
"embeddingModelPath": {
|
|
174
|
-
"type": "string"
|
|
197
|
+
"type": "string",
|
|
198
|
+
"description": "Directory visible to the daemon containing embedding.json, model.onnx, and tokenizer.json for the selected embeddingProfile."
|
|
175
199
|
},
|
|
176
200
|
"embeddingTokenizerPath": {
|
|
177
201
|
"type": "string"
|