@xdarkicex/openclaw-memory-libravdb 1.3.5 → 1.3.6
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 +24 -4
- package/docs/architecture-decisions/adr-004-sidecar-over-native-ts.md +2 -2
- package/docs/architecture.md +11 -11
- package/docs/contributing.md +5 -5
- package/docs/implementation.md +17 -9
- package/docs/installation.md +101 -45
- package/docs/mathematics.md +15 -15
- package/docs/security.md +15 -16
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -7
- package/packaging/README.md +35 -0
- package/packaging/homebrew/libravdbd.rb.tmpl +40 -0
- package/packaging/launchd/com.xdarkicex.libravdbd.plist +26 -0
- package/packaging/systemd/libravdbd.service +12 -0
- package/src/plugin-runtime.ts +1 -1
- package/src/sidecar.ts +53 -147
- package/scripts/build-sidecar.sh +0 -30
- package/scripts/postinstall.js +0 -169
- package/scripts/setup.sh +0 -20
- package/scripts/setup.ts +0 -505
- package/scripts/sidecar-release.d.ts +0 -4
- package/scripts/sidecar-release.js +0 -17
- package/sidecar/cmd/inspect_onnx/main.go +0 -105
- package/sidecar/compact/gate.go +0 -273
- package/sidecar/compact/gate_test.go +0 -85
- package/sidecar/compact/summarize.go +0 -345
- package/sidecar/compact/summarize_test.go +0 -319
- package/sidecar/compact/tokens.go +0 -11
- package/sidecar/config/config.go +0 -119
- package/sidecar/config/config_test.go +0 -75
- package/sidecar/embed/engine.go +0 -696
- package/sidecar/embed/engine_test.go +0 -349
- package/sidecar/embed/matryoshka.go +0 -93
- package/sidecar/embed/matryoshka_test.go +0 -150
- package/sidecar/embed/onnx_local.go +0 -319
- package/sidecar/embed/onnx_local_test.go +0 -159
- package/sidecar/embed/profile_contract_test.go +0 -71
- package/sidecar/embed/profile_eval_test.go +0 -923
- package/sidecar/embed/profiles.go +0 -39
- package/sidecar/go.mod +0 -21
- package/sidecar/go.sum +0 -30
- package/sidecar/health/check.go +0 -33
- package/sidecar/health/check_test.go +0 -55
- package/sidecar/main.go +0 -151
- package/sidecar/model/encoder.go +0 -222
- package/sidecar/model/registry.go +0 -262
- package/sidecar/model/registry_test.go +0 -102
- package/sidecar/model/seq2seq.go +0 -133
- package/sidecar/server/rpc.go +0 -343
- package/sidecar/server/rpc_test.go +0 -350
- package/sidecar/server/transport.go +0 -160
- package/sidecar/store/libravdb.go +0 -676
- package/sidecar/store/libravdb_test.go +0 -472
- package/sidecar/summarize/engine.go +0 -360
- package/sidecar/summarize/engine_test.go +0 -148
- package/sidecar/summarize/onnx_local.go +0 -494
- package/sidecar/summarize/onnx_local_test.go +0 -48
- package/sidecar/summarize/profiles.go +0 -52
- package/sidecar/summarize/tokenizer.go +0 -13
- package/sidecar/summarize/tokenizer_hf.go +0 -76
- package/sidecar/summarize/util.go +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xdarkicex/openclaw-memory-libravdb",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
"README.md",
|
|
10
10
|
"openclaw.plugin.json",
|
|
11
11
|
"package.json",
|
|
12
|
+
"packaging/",
|
|
12
13
|
"src/",
|
|
13
|
-
"scripts/",
|
|
14
|
-
"sidecar/",
|
|
15
14
|
"docs/",
|
|
16
15
|
"tsconfig.json",
|
|
17
16
|
"tsconfig.tests.json"
|
|
@@ -22,15 +21,13 @@
|
|
|
22
21
|
"openclaw": {
|
|
23
22
|
"extensions": [
|
|
24
23
|
"./src/index.ts"
|
|
25
|
-
]
|
|
26
|
-
"setup": "./scripts/setup.ts"
|
|
24
|
+
]
|
|
27
25
|
},
|
|
28
26
|
"scripts": {
|
|
29
27
|
"check": "./.ts-toolchain/node_modules/.bin/tsc --noEmit && pnpm run test:ts",
|
|
30
28
|
"test:ts": "./.ts-toolchain/node_modules/.bin/tsc -p tsconfig.tests.json && node --test .ts-build/test/unit/*.test.js",
|
|
31
29
|
"test:integration": "./.ts-toolchain/node_modules/.bin/tsc -p tsconfig.tests.json && node --test .ts-build/test/integration/checklist-validation.test.js .ts-build/test/integration/host-flow.test.js .ts-build/test/integration/sidecar-lifecycle.test.js",
|
|
32
|
-
"
|
|
33
|
-
"build:sidecar": "bash scripts/build-sidecar.sh"
|
|
30
|
+
"build:daemon": "bash scripts/build-daemon.sh"
|
|
34
31
|
},
|
|
35
32
|
"dependencies": {
|
|
36
33
|
"openclaw": "*"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Packaging Assets
|
|
2
|
+
|
|
3
|
+
This directory contains Phase 2 daemon-distribution assets for `libravdbd`.
|
|
4
|
+
|
|
5
|
+
- `systemd/libravdbd.service`: user-service template for Linux.
|
|
6
|
+
- `launchd/com.xdarkicex.libravdbd.plist`: LaunchAgent template for macOS.
|
|
7
|
+
- `homebrew/libravdbd.rb.tmpl`: source template used to generate a publish-ready Homebrew formula.
|
|
8
|
+
|
|
9
|
+
The templates assume the default daemon endpoint contract used by the plugin:
|
|
10
|
+
|
|
11
|
+
- macOS/Linux: `unix:$HOME/.clawdb/run/libravdb.sock`
|
|
12
|
+
- Windows: `tcp:127.0.0.1:37421`
|
|
13
|
+
|
|
14
|
+
Before loading the macOS plist, replace:
|
|
15
|
+
|
|
16
|
+
- `__LIBRAVDBD_PATH__` with the absolute path to the `libravdbd` binary
|
|
17
|
+
- `__HOME__` with the current user's home directory
|
|
18
|
+
|
|
19
|
+
The release workflow now generates `dist/libravdbd.rb` from this template using
|
|
20
|
+
the release version and SHA-256 files. If `HOMEBREW_TAP_REPO` and
|
|
21
|
+
`HOMEBREW_TAP_TOKEN` are configured in GitHub Actions, the workflow also updates
|
|
22
|
+
the tap automatically.
|
|
23
|
+
|
|
24
|
+
Expected GitHub configuration:
|
|
25
|
+
|
|
26
|
+
- repository variable `HOMEBREW_TAP_REPO`, for example `xDarkicex/homebrew-openclaw-libravdb-memory`
|
|
27
|
+
- repository secret `HOMEBREW_TAP_TOKEN` with push access to that tap repo
|
|
28
|
+
|
|
29
|
+
Template placeholders:
|
|
30
|
+
|
|
31
|
+
- `__VERSION__`
|
|
32
|
+
- `__SHA256_DARWIN_ARM64__`
|
|
33
|
+
- `__SHA256_DARWIN_AMD64__`
|
|
34
|
+
- `__SHA256_LINUX_ARM64__`
|
|
35
|
+
- `__SHA256_LINUX_AMD64__`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class Libravdbd < Formula
|
|
2
|
+
desc "Local LibraVDB daemon for the OpenClaw memory plugin"
|
|
3
|
+
homepage "https://github.com/xDarkicex/openclaw-memory-libravdb"
|
|
4
|
+
version "__VERSION__"
|
|
5
|
+
|
|
6
|
+
on_macos do
|
|
7
|
+
if Hardware::CPU.arm?
|
|
8
|
+
url "https://github.com/xDarkicex/openclaw-memory-libravdb/releases/download/v#{version}/libravdbd-darwin-arm64"
|
|
9
|
+
sha256 "__SHA256_DARWIN_ARM64__"
|
|
10
|
+
else
|
|
11
|
+
url "https://github.com/xDarkicex/openclaw-memory-libravdb/releases/download/v#{version}/libravdbd-darwin-amd64"
|
|
12
|
+
sha256 "__SHA256_DARWIN_AMD64__"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
on_linux do
|
|
17
|
+
if Hardware::CPU.arm?
|
|
18
|
+
url "https://github.com/xDarkicex/openclaw-memory-libravdb/releases/download/v#{version}/libravdbd-linux-arm64"
|
|
19
|
+
sha256 "__SHA256_LINUX_ARM64__"
|
|
20
|
+
else
|
|
21
|
+
url "https://github.com/xDarkicex/openclaw-memory-libravdb/releases/download/v#{version}/libravdbd-linux-amd64"
|
|
22
|
+
sha256 "__SHA256_LINUX_AMD64__"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def install
|
|
27
|
+
bin.install Dir["libravdbd*"].first => "libravdbd"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
service do
|
|
31
|
+
run [opt_bin/"libravdbd", "serve"]
|
|
32
|
+
environment_variables LIBRAVDB_RPC_ENDPOINT: "unix:#{ENV["HOME"]}/.clawdb/run/libravdb.sock"
|
|
33
|
+
keep_alive true
|
|
34
|
+
working_dir ENV["HOME"]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test do
|
|
38
|
+
assert_match "libravdbd", shell_output("#{bin}/libravdbd version")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>Label</key>
|
|
6
|
+
<string>com.xdarkicex.libravdbd</string>
|
|
7
|
+
<key>ProgramArguments</key>
|
|
8
|
+
<array>
|
|
9
|
+
<string>__LIBRAVDBD_PATH__</string>
|
|
10
|
+
<string>serve</string>
|
|
11
|
+
</array>
|
|
12
|
+
<key>EnvironmentVariables</key>
|
|
13
|
+
<dict>
|
|
14
|
+
<key>LIBRAVDB_RPC_ENDPOINT</key>
|
|
15
|
+
<string>unix:__HOME__/.clawdb/run/libravdb.sock</string>
|
|
16
|
+
</dict>
|
|
17
|
+
<key>RunAtLoad</key>
|
|
18
|
+
<true/>
|
|
19
|
+
<key>KeepAlive</key>
|
|
20
|
+
<true/>
|
|
21
|
+
<key>StandardOutPath</key>
|
|
22
|
+
<string>__HOME__/Library/Logs/libravdbd.log</string>
|
|
23
|
+
<key>StandardErrorPath</key>
|
|
24
|
+
<string>__HOME__/Library/Logs/libravdbd.log</string>
|
|
25
|
+
</dict>
|
|
26
|
+
</plist>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=LibraVDB daemon (user)
|
|
3
|
+
After=network.target
|
|
4
|
+
|
|
5
|
+
[Service]
|
|
6
|
+
ExecStart=%h/.local/bin/libravdbd serve
|
|
7
|
+
Restart=on-failure
|
|
8
|
+
RestartSec=5
|
|
9
|
+
Environment=LIBRAVDB_RPC_ENDPOINT=unix:%h/.clawdb/run/libravdb.sock
|
|
10
|
+
|
|
11
|
+
[Install]
|
|
12
|
+
WantedBy=default.target
|
package/src/plugin-runtime.ts
CHANGED
|
@@ -34,7 +34,7 @@ export function createPluginRuntime(
|
|
|
34
34
|
} catch {
|
|
35
35
|
// Ignore cleanup failure on startup rejection.
|
|
36
36
|
}
|
|
37
|
-
throw new Error("LibraVDB
|
|
37
|
+
throw new Error("LibraVDB daemon failed health check");
|
|
38
38
|
}
|
|
39
39
|
return { rpc, sidecar };
|
|
40
40
|
})().catch((error) => {
|
package/src/sidecar.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
1
|
import net from "node:net";
|
|
2
|
+
import os from "node:os";
|
|
4
3
|
import path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
4
|
|
|
7
5
|
import type { LoggerLike, PluginConfig, SidecarHandle, SidecarSocket } from "./types.js";
|
|
8
6
|
|
|
@@ -11,19 +9,11 @@ type DataHandler = (chunk: string) => void;
|
|
|
11
9
|
type ErrorHandler = (error: Error) => void;
|
|
12
10
|
|
|
13
11
|
export interface SidecarRuntime {
|
|
14
|
-
prepareLaunch?(cfg: PluginConfig, env: Record<string, string>): void | Promise<void>;
|
|
15
12
|
resolveEndpoint(cfg: PluginConfig): string | Promise<string>;
|
|
16
13
|
createSocket(endpoint: string): SidecarSocket;
|
|
17
14
|
scheduleRestart(delayMs: number, restart: () => void): void;
|
|
18
|
-
stop?(): void | Promise<void>;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
type HostSignal = "exit" | "SIGINT" | "SIGTERM" | "SIGHUP";
|
|
22
|
-
type HostProcessLike = {
|
|
23
|
-
once(event: HostSignal, handler: () => void): void;
|
|
24
|
-
off?(event: HostSignal, handler: () => void): void;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
17
|
class PlaceholderSocket implements SidecarSocket {
|
|
28
18
|
private readonly onData = new Set<DataHandler>();
|
|
29
19
|
private readonly onClose = new Set<CloseHandler>();
|
|
@@ -174,7 +164,7 @@ class SidecarSupervisor implements SidecarHandle {
|
|
|
174
164
|
}
|
|
175
165
|
|
|
176
166
|
async start(): Promise<SidecarSocket> {
|
|
177
|
-
const endpoint = await this.
|
|
167
|
+
const endpoint = await this.runtime.resolveEndpoint(this.cfg);
|
|
178
168
|
const socket = await this.connectEndpoint(endpoint);
|
|
179
169
|
if (this.socket instanceof SupervisorSocket) {
|
|
180
170
|
this.socket.bind(socket);
|
|
@@ -190,16 +180,9 @@ class SidecarSupervisor implements SidecarHandle {
|
|
|
190
180
|
|
|
191
181
|
async shutdown(): Promise<void> {
|
|
192
182
|
this.shuttingDown = true;
|
|
193
|
-
await this.runtime.stop?.();
|
|
194
183
|
this.socket.destroy();
|
|
195
184
|
}
|
|
196
185
|
|
|
197
|
-
private async spawnEndpoint(): Promise<string> {
|
|
198
|
-
const env = buildSidecarEnv(this.cfg);
|
|
199
|
-
await this.runtime.prepareLaunch?.(this.cfg, env);
|
|
200
|
-
return await this.runtime.resolveEndpoint(this.cfg);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
186
|
private async connectEndpoint(endpoint: string): Promise<SidecarSocket> {
|
|
204
187
|
const socket = this.runtime.createSocket(endpoint);
|
|
205
188
|
socket.on("close", () => {
|
|
@@ -208,11 +191,13 @@ class SidecarSupervisor implements SidecarHandle {
|
|
|
208
191
|
|
|
209
192
|
if (isTcpEndpoint(endpoint)) {
|
|
210
193
|
this.logger.info?.(`[libravdb] using TCP endpoint ${endpoint}`);
|
|
194
|
+
} else {
|
|
195
|
+
this.logger.info?.(`[libravdb] using Unix socket ${endpoint}`);
|
|
211
196
|
}
|
|
212
197
|
|
|
213
198
|
return await new Promise<SidecarSocket>((resolve, reject) => {
|
|
214
199
|
socket.once("connect", () => resolve(socket));
|
|
215
|
-
socket.once("error", reject);
|
|
200
|
+
socket.once("error", (error) => reject(formatConnectionError(endpoint, error)));
|
|
216
201
|
});
|
|
217
202
|
}
|
|
218
203
|
|
|
@@ -236,7 +221,7 @@ class SidecarSupervisor implements SidecarHandle {
|
|
|
236
221
|
this.runtime.scheduleRestart(backoffMs, () => {
|
|
237
222
|
void this.start().catch((error) => {
|
|
238
223
|
const message = error instanceof Error ? error.message : String(error);
|
|
239
|
-
this.logger.error(`[libravdb] sidecar
|
|
224
|
+
this.logger.error(`[libravdb] sidecar reconnect failed: ${message}`);
|
|
240
225
|
});
|
|
241
226
|
});
|
|
242
227
|
}
|
|
@@ -245,7 +230,7 @@ class SidecarSupervisor implements SidecarHandle {
|
|
|
245
230
|
export async function startSidecar(
|
|
246
231
|
cfg: PluginConfig,
|
|
247
232
|
logger: LoggerLike = console,
|
|
248
|
-
runtime: SidecarRuntime = createDefaultRuntime(
|
|
233
|
+
runtime: SidecarRuntime = createDefaultRuntime(),
|
|
249
234
|
): Promise<SidecarHandle> {
|
|
250
235
|
const supervisor = new SidecarSupervisor(cfg, logger, runtime);
|
|
251
236
|
await supervisor.start();
|
|
@@ -261,13 +246,33 @@ export function isTcpEndpoint(endpoint: string): boolean {
|
|
|
261
246
|
}
|
|
262
247
|
|
|
263
248
|
export function resolveEndpoint(cfg: PluginConfig): string {
|
|
264
|
-
const endpoint =
|
|
265
|
-
? (cfg.sidecarPath ?? "unix:/tmp/libravdb.sock")
|
|
266
|
-
: "unix:/tmp/libravdb.sock";
|
|
267
|
-
|
|
249
|
+
const endpoint = resolveConfiguredEndpoint(cfg);
|
|
268
250
|
return endpoint.replace(/^unix:/, "");
|
|
269
251
|
}
|
|
270
252
|
|
|
253
|
+
export function resolveConfiguredEndpoint(cfg: PluginConfig): string {
|
|
254
|
+
const value = cfg.sidecarPath?.trim();
|
|
255
|
+
if (!value || value === "auto") {
|
|
256
|
+
return defaultEndpoint();
|
|
257
|
+
}
|
|
258
|
+
if (!isConfiguredEndpoint(value)) {
|
|
259
|
+
throw new Error(
|
|
260
|
+
`LibraVDB sidecarPath must be a daemon endpoint like unix:/path/to/libravdb.sock or tcp:127.0.0.1:37421. Executable paths are no longer supported.`,
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
return value;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function defaultEndpoint(platform = process.platform, homeDir = os.homedir()): string {
|
|
267
|
+
if (platform === "win32") {
|
|
268
|
+
return "tcp:127.0.0.1:37421";
|
|
269
|
+
}
|
|
270
|
+
const baseDir = homeDir?.trim()
|
|
271
|
+
? path.join(homeDir, ".clawdb", "run")
|
|
272
|
+
: path.join(".", ".clawdb", "run");
|
|
273
|
+
return `unix:${path.join(baseDir, "libravdb.sock")}`;
|
|
274
|
+
}
|
|
275
|
+
|
|
271
276
|
export function buildSidecarEnv(cfg: PluginConfig): Record<string, string> {
|
|
272
277
|
const env: Record<string, string> = {};
|
|
273
278
|
|
|
@@ -356,105 +361,10 @@ export function buildSidecarEnv(cfg: PluginConfig): Record<string, string> {
|
|
|
356
361
|
return env;
|
|
357
362
|
}
|
|
358
363
|
|
|
359
|
-
|
|
360
|
-
const events: HostSignal[] = ["exit", "SIGINT", "SIGTERM", "SIGHUP"];
|
|
361
|
-
let stopped = false;
|
|
362
|
-
const stopOnce = () => {
|
|
363
|
-
if (stopped) {
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
stopped = true;
|
|
367
|
-
stop();
|
|
368
|
-
};
|
|
369
|
-
for (const event of events) {
|
|
370
|
-
host.once(event, stopOnce);
|
|
371
|
-
}
|
|
372
|
-
return () => {
|
|
373
|
-
for (const event of events) {
|
|
374
|
-
host.off?.(event, stopOnce);
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function createDefaultRuntime(logger: LoggerLike): SidecarRuntime {
|
|
380
|
-
let launchEnv: Record<string, string> = {};
|
|
381
|
-
let proc: ReturnType<typeof spawn> | null = null;
|
|
382
|
-
const stopProc = () => {
|
|
383
|
-
if (!proc || proc.killed) {
|
|
384
|
-
proc = null;
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
proc.kill();
|
|
388
|
-
proc = null;
|
|
389
|
-
};
|
|
390
|
-
const removeCleanup = installSidecarProcessCleanup(process, stopProc);
|
|
391
|
-
|
|
364
|
+
function createDefaultRuntime(): SidecarRuntime {
|
|
392
365
|
return {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
},
|
|
396
|
-
async resolveEndpoint(cfg) {
|
|
397
|
-
if (isConfiguredEndpoint(cfg.sidecarPath)) {
|
|
398
|
-
return resolveEndpoint(cfg);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const binPath = resolveBinPath(cfg.sidecarPath);
|
|
402
|
-
return await new Promise<string>((resolve, reject) => {
|
|
403
|
-
stopProc();
|
|
404
|
-
const child = spawn(binPath, [], {
|
|
405
|
-
env: {
|
|
406
|
-
...process.env,
|
|
407
|
-
...launchEnv,
|
|
408
|
-
},
|
|
409
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
410
|
-
});
|
|
411
|
-
proc = child;
|
|
412
|
-
|
|
413
|
-
let stdoutBuffer = "";
|
|
414
|
-
let settled = false;
|
|
415
|
-
|
|
416
|
-
child.stdout.setEncoding("utf8");
|
|
417
|
-
child.stdout.on("data", (chunk: string) => {
|
|
418
|
-
if (settled) {
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
stdoutBuffer += chunk;
|
|
422
|
-
const lines = stdoutBuffer.split("\n");
|
|
423
|
-
stdoutBuffer = lines.pop() ?? "";
|
|
424
|
-
const endpoint = lines.find((line) => line.trim().length > 0)?.trim();
|
|
425
|
-
if (!endpoint) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
settled = true;
|
|
429
|
-
resolve(endpoint);
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
child.stderr.setEncoding("utf8");
|
|
433
|
-
child.stderr.on("data", (chunk: string) => {
|
|
434
|
-
if (cfg.logLevel === "debug") {
|
|
435
|
-
process.stderr.write(chunk);
|
|
436
|
-
} else {
|
|
437
|
-
logger.info?.(`[libravdb] sidecar: ${chunk.trim()}`);
|
|
438
|
-
}
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
child.once("error", (error) => {
|
|
442
|
-
if (settled) {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
settled = true;
|
|
446
|
-
reject(error);
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
child.once("exit", (code) => {
|
|
450
|
-
proc = null;
|
|
451
|
-
if (settled) {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
settled = true;
|
|
455
|
-
reject(new Error(`LibraVDB sidecar exited before advertising an endpoint (code ${code ?? "unknown"})`));
|
|
456
|
-
});
|
|
457
|
-
});
|
|
366
|
+
resolveEndpoint(cfg) {
|
|
367
|
+
return resolveEndpoint(cfg);
|
|
458
368
|
},
|
|
459
369
|
createSocket(endpoint) {
|
|
460
370
|
if (isTcpEndpoint(endpoint)) {
|
|
@@ -473,34 +383,30 @@ function createDefaultRuntime(logger: LoggerLike): SidecarRuntime {
|
|
|
473
383
|
scheduleRestart(delayMs, restart) {
|
|
474
384
|
setTimeout(restart, delayMs);
|
|
475
385
|
},
|
|
476
|
-
async stop() {
|
|
477
|
-
stopProc();
|
|
478
|
-
removeCleanup();
|
|
479
|
-
},
|
|
480
386
|
};
|
|
481
387
|
}
|
|
482
388
|
|
|
483
|
-
function
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
389
|
+
function formatConnectionError(endpoint: string, error: Error): Error {
|
|
390
|
+
const code = typeof (error as NodeJS.ErrnoException).code === "string"
|
|
391
|
+
? (error as NodeJS.ErrnoException).code
|
|
392
|
+
: "";
|
|
393
|
+
if (code === "ENOENT" || code === "ECONNREFUSED") {
|
|
394
|
+
return new Error(
|
|
395
|
+
`LibraVDB daemon unavailable at ${describeEndpoint(endpoint)}. Install and start libravdbd, or set sidecarPath to a running daemon endpoint.`,
|
|
396
|
+
);
|
|
490
397
|
}
|
|
398
|
+
return error;
|
|
399
|
+
}
|
|
491
400
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
path.resolve(baseDir, "../.sidecar-bin", binaryName),
|
|
496
|
-
path.resolve(baseDir, "../../.sidecar-bin", binaryName),
|
|
497
|
-
];
|
|
498
|
-
|
|
499
|
-
for (const candidate of candidates) {
|
|
500
|
-
if (existsSync(candidate)) {
|
|
501
|
-
return candidate;
|
|
502
|
-
}
|
|
401
|
+
function describeEndpoint(endpoint: string): string {
|
|
402
|
+
if (isTcpEndpoint(endpoint)) {
|
|
403
|
+
return endpoint;
|
|
503
404
|
}
|
|
405
|
+
return `unix:${endpoint}`;
|
|
406
|
+
}
|
|
504
407
|
|
|
505
|
-
|
|
408
|
+
function isConfiguredEndpoint(value?: string): boolean {
|
|
409
|
+
return value?.startsWith("tcp:") === true || value?.startsWith("unix:") === true;
|
|
506
410
|
}
|
|
411
|
+
|
|
412
|
+
export { PlaceholderSocket };
|
package/scripts/build-sidecar.sh
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
5
|
-
OUT_DIR="$ROOT_DIR/.sidecar-bin"
|
|
6
|
-
BIN_NAME="libravdb-sidecar"
|
|
7
|
-
MODELS_DIR="$ROOT_DIR/.models"
|
|
8
|
-
OUT_MODELS_DIR="$OUT_DIR/models"
|
|
9
|
-
OUT_RUNTIME_DIR="$OUT_DIR/onnxruntime"
|
|
10
|
-
|
|
11
|
-
if [[ "${OS:-}" == "Windows_NT" ]]; then
|
|
12
|
-
BIN_NAME="libravdb-sidecar.exe"
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
mkdir -p "$OUT_DIR"
|
|
16
|
-
cd "$ROOT_DIR/sidecar"
|
|
17
|
-
GOCACHE="${GOCACHE:-/tmp/openclaw-memory-libravdb-gocache}" go build -o "$OUT_DIR/$BIN_NAME" .
|
|
18
|
-
rm -rf "$OUT_MODELS_DIR" "$OUT_RUNTIME_DIR"
|
|
19
|
-
mkdir -p "$OUT_MODELS_DIR"
|
|
20
|
-
if [[ -d "$MODELS_DIR/all-minilm-l6-v2" ]]; then
|
|
21
|
-
cp -R "$MODELS_DIR/all-minilm-l6-v2" "$OUT_MODELS_DIR/all-minilm-l6-v2"
|
|
22
|
-
fi
|
|
23
|
-
if [[ -d "$MODELS_DIR/nomic-embed-text-v1.5" ]]; then
|
|
24
|
-
cp -R "$MODELS_DIR/nomic-embed-text-v1.5" "$OUT_MODELS_DIR/nomic-embed-text-v1.5"
|
|
25
|
-
fi
|
|
26
|
-
if [[ -d "$MODELS_DIR/onnxruntime" ]]; then
|
|
27
|
-
mkdir -p "$OUT_RUNTIME_DIR"
|
|
28
|
-
cp -R "$MODELS_DIR/onnxruntime/." "$OUT_RUNTIME_DIR/"
|
|
29
|
-
fi
|
|
30
|
-
echo "built sidecar: $OUT_DIR/$BIN_NAME"
|
package/scripts/postinstall.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { chmodSync, cpSync, createWriteStream, existsSync, mkdirSync, readFileSync, renameSync, rmSync } from "node:fs";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { createHash } from "node:crypto";
|
|
7
|
-
import { spawnSync } from "node:child_process";
|
|
8
|
-
import { Readable } from "node:stream";
|
|
9
|
-
import { pipeline } from "node:stream/promises";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
import { buildSidecarReleaseAssetURL, detectSidecarReleaseTarget } from "./sidecar-release.js";
|
|
12
|
-
|
|
13
|
-
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
14
|
-
const sidecarDir = path.join(root, "sidecar");
|
|
15
|
-
const outDir = path.join(root, ".sidecar-bin");
|
|
16
|
-
const binary = process.platform === "win32" ? "libravdb-sidecar.exe" : "libravdb-sidecar";
|
|
17
|
-
const modelsDir = path.join(root, ".models");
|
|
18
|
-
const outModelsDir = path.join(outDir, "models");
|
|
19
|
-
const outRuntimeDir = path.join(outDir, "onnxruntime");
|
|
20
|
-
const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
21
|
-
|
|
22
|
-
mkdirSync(outDir, { recursive: true });
|
|
23
|
-
|
|
24
|
-
const installed = await installSidecar(pkg.version);
|
|
25
|
-
if (!installed) {
|
|
26
|
-
console.error("[openclaw-memory-libravdb] FATAL: sidecar binary could not be installed.");
|
|
27
|
-
console.error(" 1. Check your internet connection (prebuilt download failed)");
|
|
28
|
-
console.error(" 2. Or install Go >= 1.22 and retry: https://go.dev/dl/");
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
rmSync(outModelsDir, { recursive: true, force: true });
|
|
33
|
-
rmSync(outRuntimeDir, { recursive: true, force: true });
|
|
34
|
-
mkdirSync(outModelsDir, { recursive: true });
|
|
35
|
-
|
|
36
|
-
const bundledMiniLM = path.join(modelsDir, "all-minilm-l6-v2");
|
|
37
|
-
if (existsSync(bundledMiniLM)) {
|
|
38
|
-
cpSync(bundledMiniLM, path.join(outModelsDir, "all-minilm-l6-v2"), { recursive: true });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const bundledNomic = path.join(modelsDir, "nomic-embed-text-v1.5");
|
|
42
|
-
if (existsSync(bundledNomic)) {
|
|
43
|
-
cpSync(bundledNomic, path.join(outModelsDir, "nomic-embed-text-v1.5"), { recursive: true });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const runtimeBundle = path.join(modelsDir, "onnxruntime");
|
|
47
|
-
if (existsSync(runtimeBundle)) {
|
|
48
|
-
cpSync(runtimeBundle, outRuntimeDir, { recursive: true });
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function installSidecar(version) {
|
|
52
|
-
const target = detectSidecarReleaseTarget();
|
|
53
|
-
if (target) {
|
|
54
|
-
const assetUrl = buildSidecarReleaseAssetURL(version, target);
|
|
55
|
-
const checksumUrl = `${assetUrl}.sha256`;
|
|
56
|
-
const downloaded = await tryDownloadPrebuilt(assetUrl, checksumUrl, path.join(outDir, binary));
|
|
57
|
-
if (downloaded) {
|
|
58
|
-
console.log(`[openclaw-memory-libravdb] Sidecar installed (prebuilt ${target})`);
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
console.warn("[openclaw-memory-libravdb] Prebuilt binary unavailable or failed verification; attempting local go build.");
|
|
62
|
-
} else {
|
|
63
|
-
console.warn(`[openclaw-memory-libravdb] No prebuilt target for ${process.platform}-${process.arch}; attempting local go build.`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return tryGoBuild(path.join(outDir, binary));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function tryDownloadPrebuilt(assetUrl, checksumUrl, dest) {
|
|
70
|
-
try {
|
|
71
|
-
const checksum = await fetchChecksum(checksumUrl);
|
|
72
|
-
if (!checksum) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
await downloadToFile(assetUrl, dest);
|
|
76
|
-
const actual = sha256File(dest);
|
|
77
|
-
if (actual !== checksum) {
|
|
78
|
-
rmSync(dest, { force: true });
|
|
79
|
-
console.warn(`[openclaw-memory-libravdb] Prebuilt sidecar checksum mismatch for ${assetUrl}.`);
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
if (process.platform !== "win32") {
|
|
83
|
-
chmodSync(dest, 0o755);
|
|
84
|
-
}
|
|
85
|
-
return true;
|
|
86
|
-
} catch (error) {
|
|
87
|
-
rmSync(dest, { force: true });
|
|
88
|
-
console.warn(`[openclaw-memory-libravdb] Prebuilt sidecar download failed: ${formatError(error)}`);
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function tryGoBuild(dest) {
|
|
94
|
-
const goCheck = spawnSync("go", ["version"], {
|
|
95
|
-
stdio: "pipe",
|
|
96
|
-
env: process.env,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
if (goCheck.error && goCheck.error.code === "ENOENT") {
|
|
100
|
-
console.error("FATAL: Go toolchain not found on PATH. The LibraVDB sidecar cannot be built locally.");
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (goCheck.status !== 0) {
|
|
105
|
-
console.error("FATAL: Go toolchain check failed. The LibraVDB sidecar cannot be built locally.");
|
|
106
|
-
if (goCheck.stderr?.length) {
|
|
107
|
-
process.stderr.write(goCheck.stderr);
|
|
108
|
-
}
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const result = spawnSync("go", ["build", "-o", dest, "."], {
|
|
113
|
-
cwd: sidecarDir,
|
|
114
|
-
stdio: "inherit",
|
|
115
|
-
env: {
|
|
116
|
-
...process.env,
|
|
117
|
-
GOCACHE: process.env.GOCACHE ?? path.join(os.tmpdir(), "openclaw-memory-libravdb-gocache"),
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
if (result.error && result.error.code === "ENOENT") {
|
|
122
|
-
console.error("FATAL: Go toolchain disappeared while building the LibraVDB sidecar.");
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (result.status !== 0) {
|
|
127
|
-
console.error("FATAL: go build failed. The LibraVDB sidecar will not start.");
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
console.log("[openclaw-memory-libravdb] Sidecar installed (local build)");
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
async function fetchChecksum(url) {
|
|
136
|
-
try {
|
|
137
|
-
const response = await fetch(url);
|
|
138
|
-
if (!response.ok) {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
const text = (await response.text()).trim();
|
|
142
|
-
const match = text.match(/[a-f0-9]{64}/i);
|
|
143
|
-
return match ? match[0].toLowerCase() : null;
|
|
144
|
-
} catch {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
async function downloadToFile(url, dest) {
|
|
150
|
-
const response = await fetch(url);
|
|
151
|
-
if (!response.ok || !response.body) {
|
|
152
|
-
throw new Error(`download failed: ${url} (${response.status})`);
|
|
153
|
-
}
|
|
154
|
-
const tempPath = `${dest}.tmp`;
|
|
155
|
-
await pipeline(Readable.fromWeb(response.body), createWriteStream(tempPath));
|
|
156
|
-
rmSync(dest, { force: true });
|
|
157
|
-
renameSync(tempPath, dest);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function sha256File(filePath) {
|
|
161
|
-
return createHash("sha256").update(readFileSync(filePath)).digest("hex");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function formatError(error) {
|
|
165
|
-
if (error instanceof Error) {
|
|
166
|
-
return error.message;
|
|
167
|
-
}
|
|
168
|
-
return String(error);
|
|
169
|
-
}
|
package/scripts/setup.sh
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
5
|
-
MODELS_DIR="$ROOT_DIR/.models"
|
|
6
|
-
ORT_ARCHIVE="$MODELS_DIR/onnxruntime/onnxruntime-osx-arm64-1.23.0.tgz"
|
|
7
|
-
ORT_LIB="$MODELS_DIR/onnxruntime/onnxruntime-osx-arm64-1.23.0/lib/libonnxruntime.dylib"
|
|
8
|
-
|
|
9
|
-
if [[ ! -f "$ORT_ARCHIVE" ]]; then
|
|
10
|
-
echo "ONNX Runtime archive not found: $ORT_ARCHIVE" >&2
|
|
11
|
-
exit 1
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
if [[ ! -f "$ORT_LIB" ]]; then
|
|
15
|
-
echo "Unpacking ONNX Runtime..."
|
|
16
|
-
tar -xzf "$ORT_ARCHIVE" -C "$MODELS_DIR/onnxruntime/"
|
|
17
|
-
echo "Done: $ORT_LIB"
|
|
18
|
-
else
|
|
19
|
-
echo "ONNX Runtime already unpacked."
|
|
20
|
-
fi
|