memory-lancedb-pro 1.0.0 → 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
 
@@ -378,31 +378,31 @@ Cross-encoder reranking supports multiple providers via `rerankProvider`:
378
378
 
379
379
  ```bash
380
380
  # List memories
381
- openclaw memory list [--scope global] [--category fact] [--limit 20] [--json]
381
+ openclaw memory-pro list [--scope global] [--category fact] [--limit 20] [--json]
382
382
 
383
383
  # Search memories
384
- openclaw memory search "query" [--scope global] [--limit 10] [--json]
384
+ openclaw memory-pro search "query" [--scope global] [--limit 10] [--json]
385
385
 
386
386
  # View statistics
387
- openclaw memory stats [--scope global] [--json]
387
+ openclaw memory-pro stats [--scope global] [--json]
388
388
 
389
389
  # Delete a memory by ID (supports 8+ char prefix)
390
- openclaw memory delete <id>
390
+ openclaw memory-pro delete <id>
391
391
 
392
392
  # Bulk delete with filters
393
- openclaw memory delete-bulk --scope global [--before 2025-01-01] [--dry-run]
393
+ openclaw memory-pro delete-bulk --scope global [--before 2025-01-01] [--dry-run]
394
394
 
395
395
  # Export / Import
396
- openclaw memory export [--scope global] [--output memories.json]
397
- openclaw memory import memories.json [--scope global] [--dry-run]
396
+ openclaw memory-pro export [--scope global] [--output memories.json]
397
+ openclaw memory-pro import memories.json [--scope global] [--dry-run]
398
398
 
399
399
  # Re-embed all entries with a new model
400
- openclaw memory reembed --source-db /path/to/old-db [--batch-size 32] [--skip-existing]
400
+ openclaw memory-pro reembed --source-db /path/to/old-db [--batch-size 32] [--skip-existing]
401
401
 
402
402
  # Migrate from built-in memory-lancedb
403
- openclaw memory migrate check [--source /path]
404
- openclaw memory migrate run [--source /path] [--dry-run] [--skip-existing]
405
- openclaw memory migrate verify [--source /path]
403
+ openclaw memory-pro migrate check [--source /path]
404
+ openclaw memory-pro migrate run [--source /path] [--dry-run] [--skip-existing]
405
+ openclaw memory-pro migrate verify [--source /path]
406
406
  ```
407
407
 
408
408
  ---
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
 
@@ -333,31 +333,31 @@ openclaw config get plugins.slots.memory
333
333
 
334
334
  ```bash
335
335
  # 列出记忆
336
- openclaw memory list [--scope global] [--category fact] [--limit 20] [--json]
336
+ openclaw memory-pro list [--scope global] [--category fact] [--limit 20] [--json]
337
337
 
338
338
  # 搜索记忆
339
- openclaw memory search "query" [--scope global] [--limit 10] [--json]
339
+ openclaw memory-pro search "query" [--scope global] [--limit 10] [--json]
340
340
 
341
341
  # 查看统计
342
- openclaw memory stats [--scope global] [--json]
342
+ openclaw memory-pro stats [--scope global] [--json]
343
343
 
344
344
  # 按 ID 删除记忆(支持 8+ 字符前缀)
345
- openclaw memory delete <id>
345
+ openclaw memory-pro delete <id>
346
346
 
347
347
  # 批量删除
348
- openclaw memory delete-bulk --scope global [--before 2025-01-01] [--dry-run]
348
+ openclaw memory-pro delete-bulk --scope global [--before 2025-01-01] [--dry-run]
349
349
 
350
350
  # 导出 / 导入
351
- openclaw memory export [--scope global] [--output memories.json]
352
- openclaw memory import memories.json [--scope global] [--dry-run]
351
+ openclaw memory-pro export [--scope global] [--output memories.json]
352
+ openclaw memory-pro import memories.json [--scope global] [--dry-run]
353
353
 
354
354
  # 使用新模型重新生成 Embedding
355
- openclaw memory reembed --source-db /path/to/old-db [--batch-size 32] [--skip-existing]
355
+ openclaw memory-pro reembed --source-db /path/to/old-db [--batch-size 32] [--skip-existing]
356
356
 
357
357
  # 从内置 memory-lancedb 迁移
358
- openclaw memory migrate check [--source /path]
359
- openclaw memory migrate run [--source /path] [--dry-run] [--skip-existing]
360
- openclaw memory migrate verify [--source /path]
358
+ openclaw memory-pro migrate check [--source /path]
359
+ openclaw memory-pro migrate run [--source /path] [--dry-run] [--skip-existing]
360
+ openclaw memory-pro migrate verify [--source /path]
361
361
  ```
362
362
 
363
363
  ---
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];
@@ -41,8 +57,16 @@ function formatJson(obj: any): string {
41
57
 
42
58
  export function registerMemoryCLI(program: Command, context: CLIContext): void {
43
59
  const memory = program
44
- .command("memory")
45
- .description("Enhanced memory management commands");
60
+ .command("memory-pro")
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
@@ -607,5 +631,5 @@ export function registerMemoryCLI(program: Command, context: CLIContext): void {
607
631
  // ============================================================================
608
632
 
609
633
  export function createMemoryCLI(context: CLIContext) {
610
- return (program: Command) => registerMemoryCLI(program, context);
634
+ return ({ program }: { program: Command }) => registerMemoryCLI(program, context);
611
635
  }
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
  // ========================================================================
@@ -325,7 +342,7 @@ const memoryLanceDBProPlugin = {
325
342
  migrator,
326
343
  embedder,
327
344
  }),
328
- { commands: ["memory"] }
345
+ { commands: ["memory-pro"] }
329
346
  );
330
347
 
331
348
  // ========================================================================
@@ -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.0",
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
+ });