memory-lancedb-pro 1.0.1 → 1.0.3

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.
@@ -0,0 +1,24 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ cli-smoke:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+
14
+ - name: Setup Node
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: 22
18
+ cache: npm
19
+
20
+ - name: Install
21
+ run: npm ci
22
+
23
+ - name: Test
24
+ run: npm test
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ ## 1.0.3
4
+
5
+ - Fix: `memory-pro reembed` no longer crashes (missing `clampInt` helper).
6
+
7
+ ## 1.0.2
8
+
9
+ - Fix: pass through `embedding.dimensions` to the OpenAI-compatible `/embeddings` request payload when explicitly configured.
10
+ - Chore: unify plugin version fields (`openclaw.plugin.json` now matches `package.json`).
11
+
12
+ ## 1.0.1
13
+
14
+ - Fix: CLI command namespace updated to `memory-pro`.
15
+
16
+ ## 1.0.0
17
+
18
+ - Initial npm release.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- # 🧠 memory-lancedb-pro
3
+ # 🧠 memory-lancedb-pro · OpenClaw Plugin
4
4
 
5
5
  **Enhanced Long-Term Memory Plugin for [OpenClaw](https://github.com/openclaw/openclaw)**
6
6
 
package/README_CN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- # 🧠 memory-lancedb-pro
3
+ # 🧠 memory-lancedb-pro · OpenClaw Plugin
4
4
 
5
5
  **[OpenClaw](https://github.com/openclaw/openclaw) 增强型 LanceDB 长期记忆插件**
6
6
 
package/cli.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { Command } from "commander";
6
+ import { readFileSync } from "node:fs";
6
7
  import { loadLanceDB, type MemoryEntry, type MemoryStore } from "./src/store.js";
7
8
  import type { MemoryRetriever } from "./src/retriever.js";
8
9
  import type { MemoryScopeManager } from "./src/scopes.js";
@@ -24,6 +25,21 @@ interface CLIContext {
24
25
  // Utility Functions
25
26
  // ============================================================================
26
27
 
28
+ function getPluginVersion(): string {
29
+ try {
30
+ const pkgUrl = new URL("./package.json", import.meta.url);
31
+ const pkg = JSON.parse(readFileSync(pkgUrl, "utf8")) as { version?: string };
32
+ return pkg.version || "unknown";
33
+ } catch {
34
+ return "unknown";
35
+ }
36
+ }
37
+
38
+ function clampInt(value: number, min: number, max: number): number {
39
+ const n = Number.isFinite(value) ? value : min;
40
+ return Math.max(min, Math.min(max, Math.trunc(n)));
41
+ }
42
+
27
43
  function formatMemory(memory: any, index?: number): string {
28
44
  const prefix = index !== undefined ? `${index + 1}. ` : "";
29
45
  const date = new Date(memory.timestamp || memory.createdAt || Date.now()).toISOString().split('T')[0];
@@ -42,7 +58,15 @@ function formatJson(obj: any): string {
42
58
  export function registerMemoryCLI(program: Command, context: CLIContext): void {
43
59
  const memory = program
44
60
  .command("memory-pro")
45
- .description("Enhanced memory management commands");
61
+ .description("Enhanced memory management commands (LanceDB Pro)");
62
+
63
+ // Version
64
+ memory
65
+ .command("version")
66
+ .description("Print plugin version")
67
+ .action(() => {
68
+ console.log(getPluginVersion());
69
+ });
46
70
 
47
71
  // List memories
48
72
  memory
package/index.ts CHANGED
@@ -7,6 +7,7 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
7
7
  import { homedir } from "node:os";
8
8
  import { join, dirname, basename } from "node:path";
9
9
  import { readFile, readdir, writeFile, mkdir } from "node:fs/promises";
10
+ import { readFileSync } from "node:fs";
10
11
 
11
12
  // Import core components
12
13
  import { MemoryStore } from "./src/store.js";
@@ -252,6 +253,20 @@ async function findPreviousSessionFile(sessionsDir: string, currentSessionFile?:
252
253
  } catch {}
253
254
  }
254
255
 
256
+ // ============================================================================
257
+ // Version
258
+ // ============================================================================
259
+
260
+ function getPluginVersion(): string {
261
+ try {
262
+ const pkgUrl = new URL("./package.json", import.meta.url);
263
+ const pkg = JSON.parse(readFileSync(pkgUrl, "utf8")) as { version?: string };
264
+ return pkg.version || "unknown";
265
+ } catch {
266
+ return "unknown";
267
+ }
268
+ }
269
+
255
270
  // ============================================================================
256
271
  // Plugin Definition
257
272
  // ============================================================================
@@ -291,8 +306,10 @@ const memoryLanceDBProPlugin = {
291
306
  const scopeManager = createScopeManager(config.scopes);
292
307
  const migrator = createMigrator(store);
293
308
 
309
+ const pluginVersion = getPluginVersion();
310
+
294
311
  api.logger.info(
295
- `memory-lancedb-pro: plugin registered (db: ${resolvedDbPath}, model: ${config.embedding.model || "text-embedding-3-small"})`
312
+ `memory-lancedb-pro@${pluginVersion}: plugin registered (db: ${resolvedDbPath}, model: ${config.embedding.model || "text-embedding-3-small"})`
296
313
  );
297
314
 
298
315
  // ========================================================================
@@ -2,7 +2,7 @@
2
2
  "id": "memory-lancedb-pro",
3
3
  "name": "Memory (LanceDB Pro)",
4
4
  "description": "Enhanced LanceDB-backed long-term memory with hybrid retrieval, multi-scope isolation, and management CLI",
5
- "version": "2026.2.16",
5
+ "version": "1.0.3",
6
6
  "kind": "memory",
7
7
  "configSchema": {
8
8
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory-lancedb-pro",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "OpenClaw enhanced LanceDB memory plugin with hybrid retrieval (Vector + BM25), cross-encoder rerank, multi-scope isolation, and management CLI",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -32,7 +32,12 @@
32
32
  "./index.ts"
33
33
  ]
34
34
  },
35
+ "scripts": {
36
+ "test": "node test/cli-smoke.mjs"
37
+ },
35
38
  "devDependencies": {
39
+ "commander": "^14.0.0",
40
+ "jiti": "^2.6.0",
36
41
  "typescript": "^5.9.3"
37
42
  }
38
43
  }
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Non-destructive smoke test for a real OpenClaw environment where the plugin is installed.
5
+ # Intended for release preflight and on-host validation.
6
+
7
+ openclaw memory-pro version
8
+ openclaw memory-pro stats
9
+ openclaw memory-pro list --limit 3
10
+ openclaw memory-pro search "plugin" --limit 3
11
+
12
+ # export/import (dry-run)
13
+ TMP_JSON="/tmp/memory-pro-export.json"
14
+ openclaw memory-pro export --scope global --category decision --output "$TMP_JSON"
15
+ openclaw memory-pro import --dry-run "$TMP_JSON"
16
+
17
+ # delete commands (dry-run/help only)
18
+ openclaw memory-pro delete --help >/dev/null
19
+ openclaw memory-pro delete-bulk --scope global --before 1900-01-01 --dry-run
20
+
21
+ # migrate (read-only)
22
+ openclaw memory-pro migrate check
23
+
24
+ # reembed (dry-run). Adjust source-db path if needed.
25
+ if [[ -d "$HOME/.openclaw/memory/lancedb-pro" ]]; then
26
+ openclaw memory-pro reembed --source-db "$HOME/.openclaw/memory/lancedb-pro" --limit 1 --dry-run
27
+ else
28
+ echo "NOTE: $HOME/.openclaw/memory/lancedb-pro not found; skipping reembed smoke."
29
+ fi
30
+
31
+ echo "OK: openclaw smoke suite passed"
package/src/embedder.ts CHANGED
@@ -156,6 +156,9 @@ export class Embedder {
156
156
  private readonly _taskPassage?: string;
157
157
  private readonly _normalized?: boolean;
158
158
 
159
+ /** Optional requested dimensions to pass through to the embedding provider (OpenAI-compatible). */
160
+ private readonly _requestDimensions?: number;
161
+
159
162
  constructor(config: EmbeddingConfig) {
160
163
  // Resolve environment variables in API key
161
164
  const resolvedApiKey = resolveEnvVars(config.apiKey);
@@ -164,6 +167,7 @@ export class Embedder {
164
167
  this._taskQuery = config.taskQuery;
165
168
  this._taskPassage = config.taskPassage;
166
169
  this._normalized = config.normalized;
170
+ this._requestDimensions = config.dimensions;
167
171
 
168
172
  this.client = new OpenAI({
169
173
  apiKey: resolvedApiKey,
@@ -237,6 +241,13 @@ export class Embedder {
237
241
  if (task) payload.task = task;
238
242
  if (this._normalized !== undefined) payload.normalized = this._normalized;
239
243
 
244
+ // Some OpenAI-compatible providers support requesting a specific vector size.
245
+ // We only pass it through when explicitly configured to avoid breaking providers
246
+ // that reject unknown fields.
247
+ if (this._requestDimensions && this._requestDimensions > 0) {
248
+ payload.dimensions = this._requestDimensions;
249
+ }
250
+
240
251
  return payload;
241
252
  }
242
253
 
@@ -0,0 +1,92 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+
6
+ import { Command } from "commander";
7
+ import jitiFactory from "jiti";
8
+
9
+ const jiti = jitiFactory(import.meta.url, { interopDefault: true });
10
+
11
+ async function createSourceDb(sourceDbPath) {
12
+ // Create a minimal LanceDB database with a `memories` table and 1 row.
13
+ const { loadLanceDB } = jiti("../src/store.ts");
14
+ const lancedb = await loadLanceDB();
15
+ const db = await lancedb.connect(sourceDbPath);
16
+
17
+ // Create table if missing.
18
+ // LanceDB JS API supports createTable(name, data).
19
+ const row = {
20
+ id: "test_smoke_1",
21
+ text: "hello from smoke test",
22
+ category: "other",
23
+ scope: "global",
24
+ importance: 0.7,
25
+ timestamp: Date.now(),
26
+ metadata: "{}",
27
+ vector: [0, 0, 0, 0],
28
+ };
29
+
30
+ try {
31
+ await db.createTable("memories", [row]);
32
+ } catch {
33
+ // If already exists, ignore.
34
+ const table = await db.openTable("memories");
35
+ await table.add([row]);
36
+ }
37
+ }
38
+
39
+ async function runCliSmoke() {
40
+ const workDir = mkdtempSync(path.join(tmpdir(), "memory-lancedb-pro-smoke-"));
41
+ const sourceDbPath = path.join(workDir, "source-db");
42
+
43
+ await createSourceDb(sourceDbPath);
44
+
45
+ const { createMemoryCLI } = jiti("../cli.ts");
46
+
47
+ const program = new Command();
48
+ program.exitOverride();
49
+
50
+ const context = {
51
+ // Minimal store interface for reembed dry-run.
52
+ store: { dbPath: path.join(workDir, "target-db") },
53
+ retriever: {},
54
+ scopeManager: {},
55
+ migrator: {},
56
+ // Presence required, but dry-run exits before embeddings.
57
+ embedder: {},
58
+ };
59
+
60
+ // Register commands under `memory-pro`
61
+ createMemoryCLI(context)({ program });
62
+
63
+ // 1) version command should not throw
64
+ await program.parseAsync(["node", "openclaw", "memory-pro", "version"]);
65
+
66
+ // 2) reembed dry-run should not crash (regression test for clampInt)
67
+ await program.parseAsync([
68
+ "node",
69
+ "openclaw",
70
+ "memory-pro",
71
+ "reembed",
72
+ "--source-db",
73
+ sourceDbPath,
74
+ "--limit",
75
+ "1",
76
+ "--batch-size",
77
+ "999",
78
+ "--dry-run",
79
+ ]);
80
+
81
+ rmSync(workDir, { recursive: true, force: true });
82
+ }
83
+
84
+ runCliSmoke()
85
+ .then(() => {
86
+ console.log("OK: CLI smoke test passed");
87
+ })
88
+ .catch((err) => {
89
+ console.error("FAIL: CLI smoke test failed");
90
+ console.error(err);
91
+ process.exit(1);
92
+ });