@xdarkicex/openclaw-memory-libravdb 1.4.80 → 1.5.0
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 +1 -1
- package/dist/grpc-client.d.ts +18 -1
- package/dist/grpc-client.js +38 -8
- package/dist/index.js +51 -21
- package/dist/plugin-runtime.d.ts +2 -0
- package/dist/plugin-runtime.js +15 -0
- package/dist/types.d.ts +6 -0
- package/docs/TLS_configuration.md +112 -0
- package/docs/configuration.md +51 -1
- package/openclaw.plugin.json +14 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -187,7 +187,7 @@ All keys are optional. For the full reference, see [Configuration](./docs/config
|
|
|
187
187
|
|
|
188
188
|
- New install: [Install](./docs/install.md), [Installation reference](./docs/installation.md)
|
|
189
189
|
- Understand the design: [Problem](./docs/problem.md), [Architecture](./docs/architecture.md), [ADRs](./docs/architecture-decisions/README.md)
|
|
190
|
-
- Configure: [Configuration](./docs/configuration.md), [Features](./docs/features.md), [Embedding profiles](./docs/embedding-profiles.md), [Models](./docs/models.md)
|
|
190
|
+
- Configure: [Configuration](./docs/configuration.md), [TLS configuration](./docs/TLS_configuration.md), [Features](./docs/features.md), [Embedding profiles](./docs/embedding-profiles.md), [Models](./docs/models.md)
|
|
191
191
|
- Operate safely: [Security](./docs/security.md), [Uninstall](./docs/uninstall.md)
|
|
192
192
|
- Advanced operations: [Performance and tuning](./docs/performance-and-tuning.md)
|
|
193
193
|
- Work from source: [Development](./docs/development.md), [Contributing](./docs/contributing.md)
|
package/dist/grpc-client.d.ts
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
+
import * as grpc from "@grpc/grpc-js";
|
|
1
2
|
export interface GrpcClientOptions {
|
|
2
3
|
endpoint: string;
|
|
3
4
|
secret?: string;
|
|
4
5
|
timeoutMs?: number;
|
|
6
|
+
tlsCaPath?: string;
|
|
7
|
+
tlsMode?: "auto" | "tls" | "insecure";
|
|
5
8
|
}
|
|
6
9
|
export declare function resolveGrpcTarget(endpoint: string): string;
|
|
7
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Selects gRPC credential mode based on endpoint address class.
|
|
12
|
+
*
|
|
13
|
+
* - Unix socket endpoints → plaintext (local-only transport)
|
|
14
|
+
* - Loopback addresses (localhost, 127.0.0.1, ::1) → plaintext
|
|
15
|
+
* - All other TCP and DNS targets → TLS
|
|
16
|
+
*
|
|
17
|
+
* resolveGrpcCredentials uses this classification to return the
|
|
18
|
+
* appropriate grpc.ChannelCredentials. Pass tlsCaPath to load a
|
|
19
|
+
* custom CA certificate PEM file for self-signed or private CA
|
|
20
|
+
* deployments. Omit tlsCaPath for publicly trusted certificates
|
|
21
|
+
* (Let's Encrypt, cert-manager) — the system CA pool is used.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveGrpcCredentialMode(endpoint: string, tlsMode?: "auto" | "tls" | "insecure"): "insecure" | "tls";
|
|
24
|
+
export declare function resolveGrpcCredentials(endpoint: string, tlsCaPath?: string, tlsMode?: "auto" | "tls" | "insecure"): grpc.ChannelCredentials;
|
|
8
25
|
export declare class GrpcKernelClient {
|
|
9
26
|
private client;
|
|
10
27
|
private readonly secret;
|
package/dist/grpc-client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHmac } from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import * as fs from "fs";
|
|
4
5
|
import * as grpc from "@grpc/grpc-js";
|
|
5
6
|
import * as protoLoader from "@grpc/proto-loader";
|
|
6
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -10,18 +11,47 @@ const PROTO_PATH = path.resolve(__dirname, "./proto/intelligence_kernel/v1/kerne
|
|
|
10
11
|
export function resolveGrpcTarget(endpoint) {
|
|
11
12
|
return endpoint.startsWith("tcp:") ? endpoint.substring(4) : endpoint;
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Selects gRPC credential mode based on endpoint address class.
|
|
16
|
+
*
|
|
17
|
+
* - Unix socket endpoints → plaintext (local-only transport)
|
|
18
|
+
* - Loopback addresses (localhost, 127.0.0.1, ::1) → plaintext
|
|
19
|
+
* - All other TCP and DNS targets → TLS
|
|
20
|
+
*
|
|
21
|
+
* resolveGrpcCredentials uses this classification to return the
|
|
22
|
+
* appropriate grpc.ChannelCredentials. Pass tlsCaPath to load a
|
|
23
|
+
* custom CA certificate PEM file for self-signed or private CA
|
|
24
|
+
* deployments. Omit tlsCaPath for publicly trusted certificates
|
|
25
|
+
* (Let's Encrypt, cert-manager) — the system CA pool is used.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveGrpcCredentialMode(endpoint, tlsMode) {
|
|
28
|
+
if (tlsMode === "tls")
|
|
29
|
+
return "tls";
|
|
30
|
+
if (tlsMode === "insecure")
|
|
31
|
+
return "insecure";
|
|
32
|
+
// "auto" or undefined — address-based heuristic
|
|
14
33
|
const target = resolveGrpcTarget(endpoint).trim();
|
|
15
|
-
if (target.startsWith("unix:"))
|
|
34
|
+
if (target.startsWith("unix:"))
|
|
16
35
|
return "insecure";
|
|
17
|
-
}
|
|
18
36
|
const host = extractGrpcHost(target);
|
|
19
37
|
return isLoopbackHost(host) ? "insecure" : "tls";
|
|
20
38
|
}
|
|
21
|
-
function resolveGrpcCredentials(endpoint) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
39
|
+
export function resolveGrpcCredentials(endpoint, tlsCaPath, tlsMode) {
|
|
40
|
+
if (resolveGrpcCredentialMode(endpoint, tlsMode) === "insecure") {
|
|
41
|
+
return grpc.credentials.createInsecure();
|
|
42
|
+
}
|
|
43
|
+
if (tlsCaPath) {
|
|
44
|
+
let rootCerts;
|
|
45
|
+
try {
|
|
46
|
+
rootCerts = fs.readFileSync(tlsCaPath);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
50
|
+
throw new Error(`LibraVDB: failed to load TLS CA certificate from "${tlsCaPath}": ${msg}`);
|
|
51
|
+
}
|
|
52
|
+
return grpc.credentials.createSsl(rootCerts, null, null);
|
|
53
|
+
}
|
|
54
|
+
return grpc.credentials.createSsl();
|
|
25
55
|
}
|
|
26
56
|
function extractGrpcHost(target) {
|
|
27
57
|
const withoutDnsPrefix = target.startsWith("dns:///") ? target.slice("dns:///".length) : target;
|
|
@@ -54,7 +84,7 @@ export class GrpcKernelClient {
|
|
|
54
84
|
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
|
|
55
85
|
const kernelService = protoDescriptor.intelligence_kernel.v1.IntelligenceKernel;
|
|
56
86
|
const target = resolveGrpcTarget(options.endpoint);
|
|
57
|
-
this.client = new kernelService(target, resolveGrpcCredentials(options.endpoint));
|
|
87
|
+
this.client = new kernelService(target, resolveGrpcCredentials(options.endpoint, options.tlsCaPath, options.tlsMode));
|
|
58
88
|
}
|
|
59
89
|
getMetadata(signed = true) {
|
|
60
90
|
const md = new grpc.Metadata();
|
package/dist/index.js
CHANGED
|
@@ -8810,14 +8810,14 @@ var require_tls_helpers = __commonJS({
|
|
|
8810
8810
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
8811
8811
|
exports2.CIPHER_SUITES = void 0;
|
|
8812
8812
|
exports2.getDefaultRootsData = getDefaultRootsData;
|
|
8813
|
-
var
|
|
8813
|
+
var fs5 = __require("fs");
|
|
8814
8814
|
exports2.CIPHER_SUITES = process.env.GRPC_SSL_CIPHER_SUITES;
|
|
8815
8815
|
var DEFAULT_ROOTS_FILE_PATH = process.env.GRPC_DEFAULT_SSL_ROOTS_FILE_PATH;
|
|
8816
8816
|
var defaultRootsData = null;
|
|
8817
8817
|
function getDefaultRootsData() {
|
|
8818
8818
|
if (DEFAULT_ROOTS_FILE_PATH) {
|
|
8819
8819
|
if (defaultRootsData === null) {
|
|
8820
|
-
defaultRootsData =
|
|
8820
|
+
defaultRootsData = fs5.readFileSync(DEFAULT_ROOTS_FILE_PATH);
|
|
8821
8821
|
}
|
|
8822
8822
|
return defaultRootsData;
|
|
8823
8823
|
}
|
|
@@ -14324,7 +14324,7 @@ var require_fetch = __commonJS({
|
|
|
14324
14324
|
module2.exports = fetch;
|
|
14325
14325
|
var asPromise = require_aspromise();
|
|
14326
14326
|
var inquire2 = require_inquire();
|
|
14327
|
-
var
|
|
14327
|
+
var fs5 = inquire2("fs");
|
|
14328
14328
|
function fetch(filename, options, callback) {
|
|
14329
14329
|
if (typeof options === "function") {
|
|
14330
14330
|
callback = options;
|
|
@@ -14333,8 +14333,8 @@ var require_fetch = __commonJS({
|
|
|
14333
14333
|
options = {};
|
|
14334
14334
|
if (!callback)
|
|
14335
14335
|
return asPromise(fetch, this, filename, options);
|
|
14336
|
-
if (!options.xhr &&
|
|
14337
|
-
return
|
|
14336
|
+
if (!options.xhr && fs5 && fs5.readFile)
|
|
14337
|
+
return fs5.readFile(filename, function fetchReadFileCallback(err, contents) {
|
|
14338
14338
|
return err && typeof XMLHttpRequest !== "undefined" ? fetch.xhr(filename, options, callback) : err ? callback(err) : callback(null, options.binary ? contents : contents.toString("utf8"));
|
|
14339
14339
|
});
|
|
14340
14340
|
return fetch.xhr(filename, options, callback);
|
|
@@ -20608,7 +20608,7 @@ var require_util2 = __commonJS({
|
|
|
20608
20608
|
"use strict";
|
|
20609
20609
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
20610
20610
|
exports2.addCommonProtos = exports2.loadProtosWithOptionsSync = exports2.loadProtosWithOptions = void 0;
|
|
20611
|
-
var
|
|
20611
|
+
var fs5 = __require("fs");
|
|
20612
20612
|
var path5 = __require("path");
|
|
20613
20613
|
var Protobuf = require_protobufjs();
|
|
20614
20614
|
function addIncludePathResolver(root, includePaths) {
|
|
@@ -20620,7 +20620,7 @@ var require_util2 = __commonJS({
|
|
|
20620
20620
|
for (const directory of includePaths) {
|
|
20621
20621
|
const fullPath = path5.join(directory, target);
|
|
20622
20622
|
try {
|
|
20623
|
-
|
|
20623
|
+
fs5.accessSync(fullPath, fs5.constants.R_OK);
|
|
20624
20624
|
return fullPath;
|
|
20625
20625
|
} catch (err) {
|
|
20626
20626
|
continue;
|
|
@@ -30442,7 +30442,7 @@ var require_certificate_provider = __commonJS({
|
|
|
30442
30442
|
"use strict";
|
|
30443
30443
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
30444
30444
|
exports2.FileWatcherCertificateProvider = void 0;
|
|
30445
|
-
var
|
|
30445
|
+
var fs5 = __require("fs");
|
|
30446
30446
|
var logging = require_logging();
|
|
30447
30447
|
var constants_1 = require_constants();
|
|
30448
30448
|
var util_1 = __require("util");
|
|
@@ -30450,7 +30450,7 @@ var require_certificate_provider = __commonJS({
|
|
|
30450
30450
|
function trace(text) {
|
|
30451
30451
|
logging.trace(constants_1.LogVerbosity.DEBUG, TRACER_NAME, text);
|
|
30452
30452
|
}
|
|
30453
|
-
var readFilePromise = (0, util_1.promisify)(
|
|
30453
|
+
var readFilePromise = (0, util_1.promisify)(fs5.readFile);
|
|
30454
30454
|
var FileWatcherCertificateProvider = class {
|
|
30455
30455
|
constructor(config) {
|
|
30456
30456
|
this.config = config;
|
|
@@ -39661,21 +39661,37 @@ var protoLoader = __toESM(require_src2(), 1);
|
|
|
39661
39661
|
import { createHmac } from "node:crypto";
|
|
39662
39662
|
import path3 from "node:path";
|
|
39663
39663
|
import { fileURLToPath } from "node:url";
|
|
39664
|
+
import * as fs3 from "fs";
|
|
39664
39665
|
var __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
|
|
39665
39666
|
var PROTO_PATH = path3.resolve(__dirname2, "./proto/intelligence_kernel/v1/kernel.proto");
|
|
39666
39667
|
function resolveGrpcTarget(endpoint) {
|
|
39667
39668
|
return endpoint.startsWith("tcp:") ? endpoint.substring(4) : endpoint;
|
|
39668
39669
|
}
|
|
39669
|
-
function resolveGrpcCredentialMode(endpoint) {
|
|
39670
|
+
function resolveGrpcCredentialMode(endpoint, tlsMode) {
|
|
39671
|
+
if (tlsMode === "tls") return "tls";
|
|
39672
|
+
if (tlsMode === "insecure") return "insecure";
|
|
39670
39673
|
const target = resolveGrpcTarget(endpoint).trim();
|
|
39671
|
-
if (target.startsWith("unix:"))
|
|
39672
|
-
return "insecure";
|
|
39673
|
-
}
|
|
39674
|
+
if (target.startsWith("unix:")) return "insecure";
|
|
39674
39675
|
const host = extractGrpcHost(target);
|
|
39675
39676
|
return isLoopbackHost(host) ? "insecure" : "tls";
|
|
39676
39677
|
}
|
|
39677
|
-
function resolveGrpcCredentials(endpoint) {
|
|
39678
|
-
|
|
39678
|
+
function resolveGrpcCredentials(endpoint, tlsCaPath, tlsMode) {
|
|
39679
|
+
if (resolveGrpcCredentialMode(endpoint, tlsMode) === "insecure") {
|
|
39680
|
+
return grpc.credentials.createInsecure();
|
|
39681
|
+
}
|
|
39682
|
+
if (tlsCaPath) {
|
|
39683
|
+
let rootCerts;
|
|
39684
|
+
try {
|
|
39685
|
+
rootCerts = fs3.readFileSync(tlsCaPath);
|
|
39686
|
+
} catch (err) {
|
|
39687
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
39688
|
+
throw new Error(
|
|
39689
|
+
`LibraVDB: failed to load TLS CA certificate from "${tlsCaPath}": ${msg}`
|
|
39690
|
+
);
|
|
39691
|
+
}
|
|
39692
|
+
return grpc.credentials.createSsl(rootCerts, null, null);
|
|
39693
|
+
}
|
|
39694
|
+
return grpc.credentials.createSsl();
|
|
39679
39695
|
}
|
|
39680
39696
|
function extractGrpcHost(target) {
|
|
39681
39697
|
const withoutDnsPrefix = target.startsWith("dns:///") ? target.slice("dns:///".length) : target;
|
|
@@ -39708,7 +39724,7 @@ var GrpcKernelClient = class {
|
|
|
39708
39724
|
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
|
|
39709
39725
|
const kernelService = protoDescriptor.intelligence_kernel.v1.IntelligenceKernel;
|
|
39710
39726
|
const target = resolveGrpcTarget(options.endpoint);
|
|
39711
|
-
this.client = new kernelService(target, resolveGrpcCredentials(options.endpoint));
|
|
39727
|
+
this.client = new kernelService(target, resolveGrpcCredentials(options.endpoint, options.tlsCaPath, options.tlsMode));
|
|
39712
39728
|
}
|
|
39713
39729
|
getMetadata(signed = true) {
|
|
39714
39730
|
const md = new grpc.Metadata();
|
|
@@ -39782,7 +39798,7 @@ var GrpcKernelClient = class {
|
|
|
39782
39798
|
};
|
|
39783
39799
|
|
|
39784
39800
|
// src/sidecar.ts
|
|
39785
|
-
import
|
|
39801
|
+
import fs4 from "node:fs";
|
|
39786
39802
|
import net from "node:net";
|
|
39787
39803
|
import os3 from "node:os";
|
|
39788
39804
|
import path4 from "node:path";
|
|
@@ -40077,7 +40093,7 @@ function resolveConfiguredEndpoint(cfg) {
|
|
|
40077
40093
|
function daemonProvisioningHint() {
|
|
40078
40094
|
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.";
|
|
40079
40095
|
}
|
|
40080
|
-
function defaultEndpoint(platform = process.platform, homeDir = os3.homedir(), pathExists =
|
|
40096
|
+
function defaultEndpoint(platform = process.platform, homeDir = os3.homedir(), pathExists = fs4.existsSync) {
|
|
40081
40097
|
const envEndpoint = normalizeConfiguredEndpoint(process.env.LIBRAVDB_RPC_ENDPOINT);
|
|
40082
40098
|
if (envEndpoint) {
|
|
40083
40099
|
return envEndpoint;
|
|
@@ -40175,9 +40191,11 @@ function sleep2(delayMs) {
|
|
|
40175
40191
|
}
|
|
40176
40192
|
|
|
40177
40193
|
// src/plugin-runtime.ts
|
|
40178
|
-
import { readFileSync as
|
|
40194
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
40179
40195
|
var DEFAULT_RPC_TIMEOUT_MS = 3e4;
|
|
40180
40196
|
var STARTUP_HEALTH_TIMEOUT_MS = 2e3;
|
|
40197
|
+
var VALID_TLS_MODES = ["auto", "tls", "insecure"];
|
|
40198
|
+
var isTlsModeValid = (m) => VALID_TLS_MODES.includes(m);
|
|
40181
40199
|
function resolveStartupHealthTimeoutMs(cfg) {
|
|
40182
40200
|
return Math.max(STARTUP_HEALTH_TIMEOUT_MS, cfg.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS);
|
|
40183
40201
|
}
|
|
@@ -40210,10 +40228,22 @@ function createPluginRuntime(cfg, logger = console) {
|
|
|
40210
40228
|
if (cfg.grpcEndpoint) {
|
|
40211
40229
|
try {
|
|
40212
40230
|
const secret = loadSecretFromEnv();
|
|
40231
|
+
if (cfg.grpcEndpointTlsMode !== void 0 && !isTlsModeValid(cfg.grpcEndpointTlsMode)) {
|
|
40232
|
+
throw new Error(
|
|
40233
|
+
`LibraVDB: invalid grpcEndpointTlsMode "${cfg.grpcEndpointTlsMode}" \u2014 must be "auto", "tls", or "insecure"`
|
|
40234
|
+
);
|
|
40235
|
+
}
|
|
40236
|
+
if (cfg.grpcEndpointTlsMode === "insecure" && cfg.grpcEndpointTlsCa) {
|
|
40237
|
+
logger.warn?.(
|
|
40238
|
+
`LibraVDB: grpcEndpointTlsCa is set but grpcEndpointTlsMode is "insecure" \u2014 the CA file will not be used`
|
|
40239
|
+
);
|
|
40240
|
+
}
|
|
40213
40241
|
kernel = new GrpcKernelClient({
|
|
40214
40242
|
endpoint: cfg.grpcEndpoint,
|
|
40215
40243
|
secret,
|
|
40216
|
-
timeoutMs: cfg.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS
|
|
40244
|
+
timeoutMs: cfg.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS,
|
|
40245
|
+
tlsCaPath: cfg.grpcEndpointTlsCa,
|
|
40246
|
+
tlsMode: cfg.grpcEndpointTlsMode
|
|
40217
40247
|
});
|
|
40218
40248
|
} catch (error) {
|
|
40219
40249
|
logger.warn?.(`LibraVDB: failed to initialize gRPC kernel client: ${formatError(error)}`);
|
|
@@ -40282,7 +40312,7 @@ function loadSecretFromEnv() {
|
|
|
40282
40312
|
const path5 = process.env.LIBRAVDB_AUTH_SECRET_FILE;
|
|
40283
40313
|
if (path5) {
|
|
40284
40314
|
try {
|
|
40285
|
-
return
|
|
40315
|
+
return readFileSync3(path5, "utf8").trim();
|
|
40286
40316
|
} catch {
|
|
40287
40317
|
return void 0;
|
|
40288
40318
|
}
|
package/dist/plugin-runtime.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { LoggerLike, PluginConfig } from "./types.js";
|
|
|
4
4
|
export type RpcGetter = () => Promise<RpcClient>;
|
|
5
5
|
export declare const DEFAULT_RPC_TIMEOUT_MS = 30000;
|
|
6
6
|
export declare const STARTUP_HEALTH_TIMEOUT_MS = 2000;
|
|
7
|
+
export declare const VALID_TLS_MODES: readonly ["auto", "tls", "insecure"];
|
|
8
|
+
export type ValidTlsMode = typeof VALID_TLS_MODES[number];
|
|
7
9
|
export declare function resolveStartupHealthTimeoutMs(cfg: PluginConfig): number;
|
|
8
10
|
export interface LifecycleHint {
|
|
9
11
|
hook: "before_reset" | "session_end";
|
package/dist/plugin-runtime.js
CHANGED
|
@@ -5,6 +5,8 @@ import { formatError } from "./format-error.js";
|
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
export const DEFAULT_RPC_TIMEOUT_MS = 30000;
|
|
7
7
|
export const STARTUP_HEALTH_TIMEOUT_MS = 2000;
|
|
8
|
+
export const VALID_TLS_MODES = ["auto", "tls", "insecure"];
|
|
9
|
+
const isTlsModeValid = (m) => VALID_TLS_MODES.includes(m);
|
|
8
10
|
export function resolveStartupHealthTimeoutMs(cfg) {
|
|
9
11
|
return Math.max(STARTUP_HEALTH_TIMEOUT_MS, cfg.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS);
|
|
10
12
|
}
|
|
@@ -39,10 +41,23 @@ export function createPluginRuntime(cfg, logger = console) {
|
|
|
39
41
|
if (cfg.grpcEndpoint) {
|
|
40
42
|
try {
|
|
41
43
|
const secret = loadSecretFromEnv();
|
|
44
|
+
if (cfg.grpcEndpointTlsMode !== undefined &&
|
|
45
|
+
!isTlsModeValid(cfg.grpcEndpointTlsMode)) {
|
|
46
|
+
throw new Error(`LibraVDB: invalid grpcEndpointTlsMode "${cfg.grpcEndpointTlsMode}" — ` +
|
|
47
|
+
`must be "auto", "tls", or "insecure"`);
|
|
48
|
+
}
|
|
49
|
+
if (cfg.grpcEndpointTlsMode === "insecure" &&
|
|
50
|
+
cfg.grpcEndpointTlsCa) {
|
|
51
|
+
// logger is provided by the host and may not have all methods
|
|
52
|
+
logger.warn?.(`LibraVDB: grpcEndpointTlsCa is set but grpcEndpointTlsMode ` +
|
|
53
|
+
`is "insecure" — the CA file will not be used`);
|
|
54
|
+
}
|
|
42
55
|
kernel = new GrpcKernelClient({
|
|
43
56
|
endpoint: cfg.grpcEndpoint,
|
|
44
57
|
secret,
|
|
45
58
|
timeoutMs: cfg.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS,
|
|
59
|
+
tlsCaPath: cfg.grpcEndpointTlsCa,
|
|
60
|
+
tlsMode: cfg.grpcEndpointTlsMode,
|
|
46
61
|
});
|
|
47
62
|
}
|
|
48
63
|
catch (error) {
|
package/dist/types.d.ts
CHANGED
|
@@ -90,6 +90,12 @@ export interface PluginConfig {
|
|
|
90
90
|
maxRetries?: number;
|
|
91
91
|
logLevel?: "debug" | "info" | "warn" | "error";
|
|
92
92
|
grpcEndpoint?: string;
|
|
93
|
+
grpcEndpointTlsCa?: string;
|
|
94
|
+
/** Controls gRPC credential mode.
|
|
95
|
+
* "auto" (default) — loopback and unix → plaintext, remote → TLS.
|
|
96
|
+
* "tls" — always use TLS regardless of address.
|
|
97
|
+
* "insecure" — always use plaintext (service mesh, tunnel). */
|
|
98
|
+
grpcEndpointTlsMode?: "auto" | "tls" | "insecure";
|
|
93
99
|
}
|
|
94
100
|
export interface SearchResult {
|
|
95
101
|
id: string;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# TLS Configuration
|
|
2
|
+
|
|
3
|
+
The plugin selects the right credentials automatically based on which address it connects to. Unix sockets and loopback addresses (localhost, 127.0.0.1, ::1) always use plaintext. All other addresses use TLS. In most deployments no TLS configuration is needed at all. The only time manual configuration is required is when the daemon serves TLS on a loopback address, when the daemon uses a self-signed or private-CA certificate, or when infrastructure such as a service mesh handles TLS outside the plugin.
|
|
4
|
+
|
|
5
|
+
## Default behavior
|
|
6
|
+
|
|
7
|
+
The plugin applies the following rules automatically:
|
|
8
|
+
|
|
9
|
+
| Endpoint type | Credential mode |
|
|
10
|
+
|---|---|
|
|
11
|
+
| Unix socket (`unix:/path/to/socket`) | Plaintext |
|
|
12
|
+
| Loopback (`tcp:127.0.0.1:port`, `tcp:localhost:port`, `[::1]:port`) | Plaintext |
|
|
13
|
+
| Any other TCP or DNS address | TLS |
|
|
14
|
+
|
|
15
|
+
Because these rules are automatic, most users do not set any TLS-related fields. Plaintext is used where it is safe (local transport) and TLS is used where it is needed (network transport).
|
|
16
|
+
|
|
17
|
+
## Configuration fields
|
|
18
|
+
|
|
19
|
+
| Field | Type | Default | When to use |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| `grpcEndpoint` | string | — | The daemon address. Set to a unix socket path, a loopback address, or a remote host. |
|
|
22
|
+
| `grpcEndpointTlsCa` | string | — | Path to a CA certificate PEM file. Required only when the daemon certificate is self-signed or signed by a private CA not in the system certificate store. |
|
|
23
|
+
| `grpcEndpointTlsMode` | `"auto"` \| `"tls"` \| `"insecure"` | `"auto"` | Override the automatic selection. `"auto"` applies the default rules above. `"tls"` forces TLS regardless of address. `"insecure"` forces plaintext regardless of address. |
|
|
24
|
+
|
|
25
|
+
`grpcEndpointTlsMode` values explained:
|
|
26
|
+
|
|
27
|
+
- **`"auto"`** (default) — apply the automatic rules. Unix sockets and loopback use plaintext; all other addresses use TLS.
|
|
28
|
+
- **`"tls"`** — always use TLS, even for loopback addresses. Use this when the daemon has TLS enabled on a loopback address.
|
|
29
|
+
- **`"insecure"`** — always use plaintext, even for remote addresses. Use this only when a service mesh or TLS-terminating tunnel handles encryption externally.
|
|
30
|
+
|
|
31
|
+
## Deployment scenarios
|
|
32
|
+
|
|
33
|
+
### Local daemon (default)
|
|
34
|
+
|
|
35
|
+
The daemon runs on the same machine, listening on a unix socket or a loopback address.
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"grpcEndpoint": "unix:/home/user/.libravdbd/run/libravdb.sock"
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
or:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"grpcEndpoint": "tcp:127.0.0.1:9090"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The plugin automatically uses plaintext. No TLS fields are needed.
|
|
52
|
+
|
|
53
|
+
### Remote daemon with a trusted certificate
|
|
54
|
+
|
|
55
|
+
The daemon runs on a remote host and presents a certificate issued by a public CA such as Let's Encrypt or cert-manager.
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"grpcEndpoint": "tcp:libravdb.k8s.internal:9090"
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
TLS is automatic. The plugin uses the system certificate store to verify the daemon's certificate, so no additional configuration is needed.
|
|
64
|
+
|
|
65
|
+
### Remote daemon with a self-signed or private CA certificate
|
|
66
|
+
|
|
67
|
+
The daemon runs on a remote host and uses a self-signed certificate or a certificate signed by a private/internal CA not in the system certificate store.
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"grpcEndpoint": "tcp:libravdb.internal:9090",
|
|
72
|
+
"grpcEndpointTlsCa": "/etc/certs/company-ca.pem"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The CA certificate must be the certificate of the CA that signed the daemon's server certificate — not the server certificate itself. The plugin uses this CA to verify the daemon's certificate during the TLS handshake. Without it, the plugin will reject the daemon's certificate as untrusted.
|
|
77
|
+
|
|
78
|
+
### TLS on a loopback address
|
|
79
|
+
|
|
80
|
+
The daemon has TLS enabled on a loopback address. This is uncommon. The automatic rules would select plaintext for a loopback address, so an explicit override is required.
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"grpcEndpoint": "tcp:127.0.0.1:9090",
|
|
85
|
+
"grpcEndpointTlsMode": "tls"
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Set `grpcEndpointTlsMode` to `"tls"` to force the plugin to use TLS even on the loopback address. The plugin will use the system certificate store for verification. If the daemon uses a self-signed certificate, add `grpcEndpointTlsCa` as well.
|
|
90
|
+
|
|
91
|
+
## Service mesh and tunnels
|
|
92
|
+
|
|
93
|
+
When the daemon runs behind Istio, Envoy, or any other infrastructure that terminates TLS at the mesh or tunnel layer, the plugin should not attempt its own TLS. Set `grpcEndpointTlsMode` to `"insecure"` so the plugin uses plaintext and lets the mesh handle encryption:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"grpcEndpoint": "tcp:libravdb.mesh.svc:9090",
|
|
98
|
+
"grpcEndpointTlsMode": "insecure"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This applies even for remote addresses. The mesh terminates TLS at the boundary, and the plugin communicates with the mesh over plaintext on the inside.
|
|
103
|
+
|
|
104
|
+
## Error reference
|
|
105
|
+
|
|
106
|
+
| Error | Likely cause | Fix |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| `UNAVAILABLE / connection closed / TLS handshake failed` when connecting to a loopback address | The daemon has TLS enabled on a loopback address but the plugin is using plaintext (the default for loopback). | Add `"grpcEndpointTlsMode": "tls"` to the plugin config. |
|
|
109
|
+
| `x509: certificate signed by unknown authority` | The daemon uses a self-signed certificate or a certificate from a private CA not trusted by the system. | Set `grpcEndpointTlsCa` to the path of the CA certificate PEM file that signed the daemon's server certificate. |
|
|
110
|
+
| `failed to load TLS CA certificate from "...": ENOENT: no such file or directory` | The file path given in `grpcEndpointTlsCa` does not exist on the machine. | Verify the file path is correct and the CA certificate file exists. |
|
|
111
|
+
| `LibraVDB: invalid grpcEndpointTlsMode "..."` | The value set in `grpcEndpointTlsMode` is not one of the accepted values. | Change the value to `"auto"`, `"tls"`, or `"insecure"`. |
|
|
112
|
+
| `LIBRAVDB: grpcEndpointTlsCa is set but grpcEndpointTlsMode is "insecure"` (warning) | Both `grpcEndpointTlsCa` and `grpcEndpointTlsMode: "insecure"` are set. The CA file will not be used. | Remove `grpcEndpointTlsCa` if plaintext is intended, or change `grpcEndpointTlsMode` to `"auto"` or `"tls"` to use the CA file. |
|
package/docs/configuration.md
CHANGED
|
@@ -12,10 +12,60 @@ CPU when a provider is unavailable.
|
|
|
12
12
|
| Key | Type | Default | Notes |
|
|
13
13
|
|---|---|---|---|
|
|
14
14
|
| `sidecarPath` | string | `auto` | `"auto"` probes standard socket paths; set `unix:/path` or `tcp:host:port` to override |
|
|
15
|
-
| `grpcEndpoint` | string | — |
|
|
15
|
+
| `grpcEndpoint` | string | — | gRPC kernel endpoint. See `grpcEndpointTlsMode` for credential control. |
|
|
16
|
+
| `grpcEndpointTlsCa` | string | — | Path to CA certificate PEM file. Only needed for self-signed or private CA certs. Omit when using Let's Encrypt or cert-manager. |
|
|
17
|
+
| `grpcEndpointTlsMode` | string | `"auto"` | gRPC credential mode. `"auto"`: loopback/unix → plaintext, remote → TLS. `"tls"`: always TLS. `"insecure"`: always plaintext. |
|
|
16
18
|
| `rpcTimeoutMs` | number | `30000` | Per-call timeout for service RPC (ms) |
|
|
17
19
|
| `dbPath` | string | auto-named | Explicit DB path; when set bypasses model-specific naming |
|
|
18
20
|
|
|
21
|
+
### gRPC TLS behavior
|
|
22
|
+
|
|
23
|
+
The plugin selects credentials automatically based on the endpoint:
|
|
24
|
+
|
|
25
|
+
| Endpoint format | Credential mode |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `unix:/path/to/sock` | Plaintext (local) |
|
|
28
|
+
| `tcp:127.0.0.1:port` / `tcp:localhost:port` / `[::1]:port` | Plaintext (loopback) |
|
|
29
|
+
| Any other TCP or DNS target | TLS |
|
|
30
|
+
|
|
31
|
+
Use `grpcEndpointTlsMode` to override the default behavior:
|
|
32
|
+
|
|
33
|
+
| Value | When to use |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `"auto"` (default) | Standard operation — plugin heuristic matches daemon TLS setting automatically. |
|
|
36
|
+
| `"tls"` | Daemon has TLS enabled on loopback or unix socket (rare; use when the daemon's `LIBRAVDB_GRPC_TLS_*` env vars are set on a local address). |
|
|
37
|
+
| `"insecure"` | Service mesh or TLS-terminating tunnel handles encryption externally; both sides are plaintext. |
|
|
38
|
+
|
|
39
|
+
**Default (local daemon):** No TLS configuration needed.
|
|
40
|
+
Unix socket and loopback endpoints are always plaintext regardless
|
|
41
|
+
of any TLS settings.
|
|
42
|
+
|
|
43
|
+
**K8 / remote daemon with CA-issued cert:**
|
|
44
|
+
No extra configuration needed. The plugin uses the system CA pool,
|
|
45
|
+
which trusts certs issued by Let's Encrypt, cert-manager, and
|
|
46
|
+
other public CAs automatically.
|
|
47
|
+
|
|
48
|
+
**Remote daemon with self-signed or private CA cert:**
|
|
49
|
+
Set `grpcEndpointTlsCa` to the path of the CA certificate PEM file:
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"grpcEndpoint": "tcp:yourdaemon.internal:50051",
|
|
53
|
+
"grpcEndpointTlsCa": "/etc/certs/ca.pem"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
The daemon must be configured with matching TLS cert and key via
|
|
57
|
+
`LIBRAVDB_GRPC_TLS_CERT` and `LIBRAVDB_GRPC_TLS_KEY`.
|
|
58
|
+
|
|
59
|
+
**Local daemon with TLS enabled:**
|
|
60
|
+
If the daemon has `LIBRAVDB_GRPC_TLS_CERT`/`LIBRAVDB_GRPC_TLS_KEY` set on a loopback
|
|
61
|
+
address, explicitly set `grpcEndpointTlsMode: "tls"` to match:
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"grpcEndpoint": "tcp:127.0.0.1:9090",
|
|
65
|
+
"grpcEndpointTlsMode": "tls"
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
19
69
|
## Embedding
|
|
20
70
|
|
|
21
71
|
| Key | Type | Default | Notes |
|
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.
|
|
5
|
+
"version": "1.5.0",
|
|
6
6
|
"kind": [
|
|
7
7
|
"memory",
|
|
8
8
|
"context-engine"
|
|
@@ -46,6 +46,19 @@
|
|
|
46
46
|
"type": "string",
|
|
47
47
|
"description": "Optional gRPC kernel endpoint for hosts using the daemon kernel transport."
|
|
48
48
|
},
|
|
49
|
+
"grpcEndpointTlsCa": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": "Path to a CA certificate PEM file for verifying the daemon's TLS certificate. Only needed for self-signed or private CA certificates. Not required when using a publicly trusted certificate (Let's Encrypt, cert-manager, etc)."
|
|
52
|
+
},
|
|
53
|
+
"grpcEndpointTlsMode": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"enum": [
|
|
56
|
+
"auto",
|
|
57
|
+
"tls",
|
|
58
|
+
"insecure"
|
|
59
|
+
],
|
|
60
|
+
"description": "gRPC credential mode. auto (default): loopback and unix socket use plaintext, remote addresses use TLS. tls: always use TLS regardless of address. insecure: always use plaintext (use with service mesh or tunnel that handles TLS externally)."
|
|
61
|
+
},
|
|
49
62
|
"authoredHardBudgetFraction": {
|
|
50
63
|
"type": "number",
|
|
51
64
|
"minimum": 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xdarkicex/openclaw-memory-libravdb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"pluginSdkVersion": "2026.4.11"
|
|
44
44
|
},
|
|
45
45
|
"install": {
|
|
46
|
-
"minHostVersion": ">=2026.
|
|
46
|
+
"minHostVersion": ">=2026.4.11"
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|