@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.
Files changed (61) hide show
  1. package/README.md +24 -4
  2. package/docs/architecture-decisions/adr-004-sidecar-over-native-ts.md +2 -2
  3. package/docs/architecture.md +11 -11
  4. package/docs/contributing.md +5 -5
  5. package/docs/implementation.md +17 -9
  6. package/docs/installation.md +101 -45
  7. package/docs/mathematics.md +15 -15
  8. package/docs/security.md +15 -16
  9. package/openclaw.plugin.json +1 -1
  10. package/package.json +4 -7
  11. package/packaging/README.md +35 -0
  12. package/packaging/homebrew/libravdbd.rb.tmpl +40 -0
  13. package/packaging/launchd/com.xdarkicex.libravdbd.plist +26 -0
  14. package/packaging/systemd/libravdbd.service +12 -0
  15. package/src/plugin-runtime.ts +1 -1
  16. package/src/sidecar.ts +53 -147
  17. package/scripts/build-sidecar.sh +0 -30
  18. package/scripts/postinstall.js +0 -169
  19. package/scripts/setup.sh +0 -20
  20. package/scripts/setup.ts +0 -505
  21. package/scripts/sidecar-release.d.ts +0 -4
  22. package/scripts/sidecar-release.js +0 -17
  23. package/sidecar/cmd/inspect_onnx/main.go +0 -105
  24. package/sidecar/compact/gate.go +0 -273
  25. package/sidecar/compact/gate_test.go +0 -85
  26. package/sidecar/compact/summarize.go +0 -345
  27. package/sidecar/compact/summarize_test.go +0 -319
  28. package/sidecar/compact/tokens.go +0 -11
  29. package/sidecar/config/config.go +0 -119
  30. package/sidecar/config/config_test.go +0 -75
  31. package/sidecar/embed/engine.go +0 -696
  32. package/sidecar/embed/engine_test.go +0 -349
  33. package/sidecar/embed/matryoshka.go +0 -93
  34. package/sidecar/embed/matryoshka_test.go +0 -150
  35. package/sidecar/embed/onnx_local.go +0 -319
  36. package/sidecar/embed/onnx_local_test.go +0 -159
  37. package/sidecar/embed/profile_contract_test.go +0 -71
  38. package/sidecar/embed/profile_eval_test.go +0 -923
  39. package/sidecar/embed/profiles.go +0 -39
  40. package/sidecar/go.mod +0 -21
  41. package/sidecar/go.sum +0 -30
  42. package/sidecar/health/check.go +0 -33
  43. package/sidecar/health/check_test.go +0 -55
  44. package/sidecar/main.go +0 -151
  45. package/sidecar/model/encoder.go +0 -222
  46. package/sidecar/model/registry.go +0 -262
  47. package/sidecar/model/registry_test.go +0 -102
  48. package/sidecar/model/seq2seq.go +0 -133
  49. package/sidecar/server/rpc.go +0 -343
  50. package/sidecar/server/rpc_test.go +0 -350
  51. package/sidecar/server/transport.go +0 -160
  52. package/sidecar/store/libravdb.go +0 -676
  53. package/sidecar/store/libravdb_test.go +0 -472
  54. package/sidecar/summarize/engine.go +0 -360
  55. package/sidecar/summarize/engine_test.go +0 -148
  56. package/sidecar/summarize/onnx_local.go +0 -494
  57. package/sidecar/summarize/onnx_local_test.go +0 -48
  58. package/sidecar/summarize/profiles.go +0 -52
  59. package/sidecar/summarize/tokenizer.go +0 -13
  60. package/sidecar/summarize/tokenizer_hf.go +0 -76
  61. 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.5",
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
- "postinstall": "node scripts/postinstall.js",
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
@@ -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 sidecar failed health check");
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.spawnEndpoint();
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 restart failed: ${message}`);
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(logger),
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 = isConfiguredEndpoint(cfg.sidecarPath)
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
- export function installSidecarProcessCleanup(host: HostProcessLike, stop: () => void): () => void {
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
- prepareLaunch(_cfg, env) {
394
- launchEnv = { ...env };
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 isConfiguredEndpoint(value?: string): boolean {
484
- return value?.startsWith("tcp:") === true || value?.startsWith("unix:") === true;
485
- }
486
-
487
- function resolveBinPath(sidecarPath?: string): string {
488
- if (sidecarPath && sidecarPath !== "auto") {
489
- return sidecarPath;
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
- const binaryName = process.platform === "win32" ? "libravdb-sidecar.exe" : "libravdb-sidecar";
493
- const baseDir = path.dirname(fileURLToPath(import.meta.url));
494
- const candidates = [
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
- return candidates[0];
408
+ function isConfiguredEndpoint(value?: string): boolean {
409
+ return value?.startsWith("tcp:") === true || value?.startsWith("unix:") === true;
506
410
  }
411
+
412
+ export { PlaceholderSocket };
@@ -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"
@@ -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