memory-lancedb-pro 1.0.21 → 1.0.23

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,81 @@
1
+ name: 🐛 Bug Report
2
+ description: Report a bug or unexpected behavior
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for reporting a bug! Please fill out the sections below.
9
+
10
+ - type: input
11
+ id: version
12
+ attributes:
13
+ label: Plugin Version
14
+ description: "Run `openclaw memory-pro version` to check"
15
+ placeholder: "e.g. 1.0.22"
16
+ validations:
17
+ required: true
18
+
19
+ - type: input
20
+ id: openclaw-version
21
+ attributes:
22
+ label: OpenClaw Version
23
+ description: "Run `openclaw --version` to check"
24
+ placeholder: "e.g. 2026.3.1"
25
+ validations:
26
+ required: true
27
+
28
+ - type: textarea
29
+ id: description
30
+ attributes:
31
+ label: Bug Description
32
+ description: A clear description of what happened
33
+ placeholder: "When I run `openclaw memory-pro search ...`, it throws..."
34
+ validations:
35
+ required: true
36
+
37
+ - type: textarea
38
+ id: expected
39
+ attributes:
40
+ label: Expected Behavior
41
+ description: What did you expect to happen?
42
+ validations:
43
+ required: true
44
+
45
+ - type: textarea
46
+ id: reproduce
47
+ attributes:
48
+ label: Steps to Reproduce
49
+ description: Minimal steps to reproduce the issue
50
+ placeholder: |
51
+ 1. Set config ...
52
+ 2. Run command ...
53
+ 3. See error ...
54
+ validations:
55
+ required: true
56
+
57
+ - type: textarea
58
+ id: logs
59
+ attributes:
60
+ label: Error Logs / Screenshots
61
+ description: Paste relevant error output or screenshots
62
+ render: shell
63
+
64
+ - type: dropdown
65
+ id: embedding
66
+ attributes:
67
+ label: Embedding Provider
68
+ options:
69
+ - OpenAI
70
+ - Jina
71
+ - Gemini
72
+ - Ollama
73
+ - Other
74
+ validations:
75
+ required: false
76
+
77
+ - type: input
78
+ id: os
79
+ attributes:
80
+ label: OS / Platform
81
+ placeholder: "e.g. Ubuntu 24.04, macOS 15, Windows 11"
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: ❓ Question / Help
4
+ url: https://discord.com/invite/clawd
5
+ about: For questions and support, join the OpenClaw Discord community
@@ -0,0 +1,57 @@
1
+ name: ✨ Feature Request
2
+ description: Suggest a new feature or improvement
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for suggesting a feature! Please describe your idea below.
9
+
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: Problem / Motivation
14
+ description: What problem does this solve? Why do you need it?
15
+ placeholder: "I often need to ... but currently there's no way to ..."
16
+ validations:
17
+ required: true
18
+
19
+ - type: textarea
20
+ id: solution
21
+ attributes:
22
+ label: Proposed Solution
23
+ description: How would you like this to work?
24
+ placeholder: "It would be great if `openclaw memory-pro` could ..."
25
+ validations:
26
+ required: true
27
+
28
+ - type: textarea
29
+ id: alternatives
30
+ attributes:
31
+ label: Alternatives Considered
32
+ description: Any workarounds or alternative approaches you've tried?
33
+
34
+ - type: dropdown
35
+ id: scope
36
+ attributes:
37
+ label: Area
38
+ description: Which part of the plugin does this affect?
39
+ options:
40
+ - Retrieval / Search
41
+ - Storage / Database
42
+ - Embedding
43
+ - CLI Commands
44
+ - Configuration
45
+ - Auto-capture / Auto-recall
46
+ - Scopes / Access Control
47
+ - Migration
48
+ - Documentation
49
+ - Other
50
+ validations:
51
+ required: false
52
+
53
+ - type: textarea
54
+ id: context
55
+ attributes:
56
+ label: Additional Context
57
+ description: Screenshots, examples, or links that help explain the feature
package/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## 1.0.22
5
+
6
+ **Storage Path Validation & Better Error Messages**
7
+
8
+ - **Fix**: Validate `dbPath` at startup — resolve symlinks, auto-create missing directories, check write permissions (#26, #27)
9
+ - **Fix**: Write/connection failures now include `errno`, resolved path, and actionable fix suggestions instead of generic errors (#28)
10
+ - **New**: Exported `validateStoragePath()` utility for external tooling and diagnostics
11
+
12
+ Breaking changes: None. Backward compatible.
13
+
14
+ ---
15
+
4
16
  ## 1.0.21
5
17
 
6
18
  **Long Context Chunking**
package/README.md CHANGED
@@ -720,6 +720,42 @@ upgrade to **memory-lancedb-pro >= 1.0.14**. This plugin now coerces these value
720
720
 
721
721
  ---
722
722
 
723
+ ## Contributors
724
+
725
+ Top contributors (from GitHub’s contributors list, sorted by commit contributions; bots excluded):
726
+
727
+ <p>
728
+ <a href="https://github.com/win4r"><img src="https://avatars.githubusercontent.com/u/42172631?v=4" width="48" height="48" alt="@win4r" /></a>
729
+ <a href="https://github.com/kctony"><img src="https://avatars.githubusercontent.com/u/1731141?v=4" width="48" height="48" alt="@kctony" /></a>
730
+ <a href="https://github.com/Akatsuki-Ryu"><img src="https://avatars.githubusercontent.com/u/8062209?v=4" width="48" height="48" alt="@Akatsuki-Ryu" /></a>
731
+ <a href="https://github.com/JasonSuz"><img src="https://avatars.githubusercontent.com/u/612256?v=4" width="48" height="48" alt="@JasonSuz" /></a>
732
+ <a href="https://github.com/Minidoracat"><img src="https://avatars.githubusercontent.com/u/11269639?v=4" width="48" height="48" alt="@Minidoracat" /></a>
733
+ <a href="https://github.com/furedericca-lab"><img src="https://avatars.githubusercontent.com/u/263020793?v=4" width="48" height="48" alt="@furedericca-lab" /></a>
734
+ <a href="https://github.com/joe2643"><img src="https://avatars.githubusercontent.com/u/19421931?v=4" width="48" height="48" alt="@joe2643" /></a>
735
+ <a href="https://github.com/AliceLJY"><img src="https://avatars.githubusercontent.com/u/136287420?v=4" width="48" height="48" alt="@AliceLJY" /></a>
736
+ </p>
737
+
738
+ - [@win4r](https://github.com/win4r) (3 commits)
739
+ - [@kctony](https://github.com/kctony) (2 commits)
740
+ - [@Akatsuki-Ryu](https://github.com/Akatsuki-Ryu) (1 commit)
741
+ - [@AliceLJY](https://github.com/AliceLJY) (1 commit)
742
+ - [@JasonSuz](https://github.com/JasonSuz) (1 commit)
743
+ - [@Minidoracat](https://github.com/Minidoracat) (1 commit)
744
+ - [@furedericca-lab](https://github.com/furedericca-lab) (1 commit)
745
+ - [@joe2643](https://github.com/joe2643) (1 commit)
746
+
747
+ Full list: https://github.com/win4r/memory-lancedb-pro/graphs/contributors
748
+
749
+ ## ⭐ Star History
750
+
751
+ <a href="https://star-history.com/#win4r/memory-lancedb-pro&Date">
752
+ <picture>
753
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=win4r/memory-lancedb-pro&type=Date&theme=dark&transparent=true" />
754
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=win4r/memory-lancedb-pro&type=Date&transparent=true" />
755
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=win4r/memory-lancedb-pro&type=Date&transparent=true" />
756
+ </picture>
757
+ </a>
758
+
723
759
  ## License
724
760
 
725
761
  MIT
package/README_CN.md CHANGED
@@ -594,6 +594,42 @@ LanceDB 表 `memories`:
594
594
 
595
595
  ---
596
596
 
597
+ ## 主要贡献者
598
+
599
+ 按 GitHub Contributors 列表自动生成(按 commit 贡献数排序,已排除 bot):
600
+
601
+ <p>
602
+ <a href="https://github.com/win4r"><img src="https://avatars.githubusercontent.com/u/42172631?v=4" width="48" height="48" alt="@win4r" /></a>
603
+ <a href="https://github.com/kctony"><img src="https://avatars.githubusercontent.com/u/1731141?v=4" width="48" height="48" alt="@kctony" /></a>
604
+ <a href="https://github.com/Akatsuki-Ryu"><img src="https://avatars.githubusercontent.com/u/8062209?v=4" width="48" height="48" alt="@Akatsuki-Ryu" /></a>
605
+ <a href="https://github.com/JasonSuz"><img src="https://avatars.githubusercontent.com/u/612256?v=4" width="48" height="48" alt="@JasonSuz" /></a>
606
+ <a href="https://github.com/Minidoracat"><img src="https://avatars.githubusercontent.com/u/11269639?v=4" width="48" height="48" alt="@Minidoracat" /></a>
607
+ <a href="https://github.com/furedericca-lab"><img src="https://avatars.githubusercontent.com/u/263020793?v=4" width="48" height="48" alt="@furedericca-lab" /></a>
608
+ <a href="https://github.com/joe2643"><img src="https://avatars.githubusercontent.com/u/19421931?v=4" width="48" height="48" alt="@joe2643" /></a>
609
+ <a href="https://github.com/AliceLJY"><img src="https://avatars.githubusercontent.com/u/136287420?v=4" width="48" height="48" alt="@AliceLJY" /></a>
610
+ </p>
611
+
612
+ - [@win4r](https://github.com/win4r)(3 次提交)
613
+ - [@kctony](https://github.com/kctony)(2 次提交)
614
+ - [@Akatsuki-Ryu](https://github.com/Akatsuki-Ryu)(1 次提交)
615
+ - [@AliceLJY](https://github.com/AliceLJY)(1 次提交)
616
+ - [@JasonSuz](https://github.com/JasonSuz)(1 次提交)
617
+ - [@Minidoracat](https://github.com/Minidoracat)(1 次提交)
618
+ - [@furedericca-lab](https://github.com/furedericca-lab)(1 次提交)
619
+ - [@joe2643](https://github.com/joe2643)(1 次提交)
620
+
621
+ 完整列表:https://github.com/win4r/memory-lancedb-pro/graphs/contributors
622
+
623
+ ## ⭐ Star 趋势
624
+
625
+ <a href="https://star-history.com/#win4r/memory-lancedb-pro&Date">
626
+ <picture>
627
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=win4r/memory-lancedb-pro&type=Date&theme=dark&transparent=true" />
628
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=win4r/memory-lancedb-pro&type=Date&transparent=true" />
629
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=win4r/memory-lancedb-pro&type=Date&transparent=true" />
630
+ </picture>
631
+ </a>
632
+
597
633
  ## License
598
634
 
599
635
  MIT
package/index.ts CHANGED
@@ -10,7 +10,7 @@ import { readFile, readdir, writeFile, mkdir } from "node:fs/promises";
10
10
  import { readFileSync } from "node:fs";
11
11
 
12
12
  // Import core components
13
- import { MemoryStore } from "./src/store.js";
13
+ import { MemoryStore, validateStoragePath } from "./src/store.js";
14
14
  import { createEmbedder, getVectorDimensions } from "./src/embedder.js";
15
15
  import { createRetriever, DEFAULT_RETRIEVAL_CONFIG } from "./src/retriever.js";
16
16
  import { createScopeManager } from "./src/scopes.js";
@@ -315,6 +315,18 @@ const memoryLanceDBProPlugin = {
315
315
  const config = parsePluginConfig(api.pluginConfig);
316
316
 
317
317
  const resolvedDbPath = api.resolvePath(config.dbPath || getDefaultDbPath());
318
+
319
+ // Pre-flight: validate storage path (symlink resolution, mkdir, write check).
320
+ // Runs synchronously and logs warnings; does NOT block gateway startup.
321
+ try {
322
+ validateStoragePath(resolvedDbPath);
323
+ } catch (err) {
324
+ api.logger.warn(
325
+ `memory-lancedb-pro: storage path issue — ${String(err)}\n` +
326
+ ` The plugin will still attempt to start, but writes may fail.`
327
+ );
328
+ }
329
+
318
330
  const vectorDim = getVectorDimensions(
319
331
  config.embedding.model || "text-embedding-3-small",
320
332
  config.embedding.dimensions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory-lancedb-pro",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "OpenClaw enhanced LanceDB memory plugin with hybrid retrieval (Vector + BM25), cross-encoder rerank, multi-scope isolation, long-context chunking, and management CLI",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/src/store.ts CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  import type * as LanceDB from "@lancedb/lancedb";
6
6
  import { randomUUID } from "node:crypto";
7
+ import { existsSync, accessSync, constants, mkdirSync, realpathSync, lstatSync } from "node:fs";
8
+ import { dirname } from "node:path";
7
9
 
8
10
  // ============================================================================
9
11
  // Types
@@ -60,6 +62,72 @@ function escapeSqlLiteral(value: string): string {
60
62
  return value.replace(/'/g, "''");
61
63
  }
62
64
 
65
+ // ============================================================================
66
+ // Storage Path Validation
67
+ // ============================================================================
68
+
69
+ /**
70
+ * Validate and prepare the storage directory before LanceDB connection.
71
+ * Resolves symlinks, creates missing directories, and checks write permissions.
72
+ * Returns the resolved absolute path on success, or throws a descriptive error.
73
+ */
74
+ export function validateStoragePath(dbPath: string): string {
75
+ let resolvedPath = dbPath;
76
+
77
+ // Resolve symlinks (including dangling symlinks)
78
+ try {
79
+ const stats = lstatSync(dbPath);
80
+ if (stats.isSymbolicLink()) {
81
+ try {
82
+ resolvedPath = realpathSync(dbPath);
83
+ } catch (err: any) {
84
+ throw new Error(
85
+ `dbPath "${dbPath}" is a symlink whose target does not exist.\n` +
86
+ ` Fix: Create the target directory, or update the symlink to point to a valid path.\n` +
87
+ ` Details: ${err.code || ""} ${err.message}`
88
+ );
89
+ }
90
+ }
91
+ } catch (err: any) {
92
+ // Missing path is OK (it will be created below)
93
+ if (err?.code === "ENOENT") {
94
+ // no-op
95
+ } else if (typeof err?.message === "string" && err.message.includes("symlink whose target does not exist")) {
96
+ throw err;
97
+ } else {
98
+ // Other lstat failures — continue with original path
99
+ }
100
+ }
101
+
102
+ // Create directory if it doesn't exist
103
+ if (!existsSync(resolvedPath)) {
104
+ try {
105
+ mkdirSync(resolvedPath, { recursive: true });
106
+ } catch (err: any) {
107
+ throw new Error(
108
+ `Failed to create dbPath directory "${resolvedPath}".\n` +
109
+ ` Fix: Ensure the parent directory "${dirname(resolvedPath)}" exists and is writable,\n` +
110
+ ` or create it manually: mkdir -p "${resolvedPath}"\n` +
111
+ ` Details: ${err.code || ""} ${err.message}`
112
+ );
113
+ }
114
+ }
115
+
116
+ // Check write permissions
117
+ try {
118
+ accessSync(resolvedPath, constants.W_OK);
119
+ } catch (err: any) {
120
+ throw new Error(
121
+ `dbPath directory "${resolvedPath}" is not writable.\n` +
122
+ ` Fix: Check permissions with: ls -la "${dirname(resolvedPath)}"\n` +
123
+ ` Or grant write access: chmod u+w "${resolvedPath}"\n` +
124
+ ` Details: ${err.code || ""} ${err.message}`
125
+ );
126
+ }
127
+
128
+ return resolvedPath;
129
+ }
130
+
63
131
  // ============================================================================
64
132
  // Memory Store
65
133
  // ============================================================================
@@ -95,7 +163,19 @@ export class MemoryStore {
95
163
 
96
164
  private async doInitialize(): Promise<void> {
97
165
  const lancedb = await loadLanceDB();
98
- const db = await lancedb.connect(this.config.dbPath);
166
+
167
+ let db: LanceDB.Connection;
168
+ try {
169
+ db = await lancedb.connect(this.config.dbPath);
170
+ } catch (err: any) {
171
+ const code = err.code || "";
172
+ const message = err.message || String(err);
173
+ throw new Error(
174
+ `Failed to open LanceDB at "${this.config.dbPath}": ${code} ${message}\n` +
175
+ ` Fix: Verify the path exists and is writable. Check parent directory permissions.`
176
+ );
177
+ }
178
+
99
179
  let table: LanceDB.Table;
100
180
 
101
181
  // Idempotent table init: try openTable first, create only if missing,
@@ -196,7 +276,15 @@ export class MemoryStore {
196
276
  metadata: entry.metadata || "{}",
197
277
  };
198
278
 
199
- await this.table!.add([fullEntry]);
279
+ try {
280
+ await this.table!.add([fullEntry]);
281
+ } catch (err: any) {
282
+ const code = err.code || "";
283
+ const message = err.message || String(err);
284
+ throw new Error(
285
+ `Failed to store memory in "${this.config.dbPath}": ${code} ${message}`
286
+ );
287
+ }
200
288
  return fullEntry;
201
289
  }
202
290
 
package/src/tools.ts CHANGED
@@ -26,6 +26,12 @@ interface ToolContext {
26
26
  agentId?: string;
27
27
  }
28
28
 
29
+ function resolveAgentId(runtimeAgentId: unknown, fallback?: string): string | undefined {
30
+ if (typeof runtimeAgentId === "string" && runtimeAgentId.trim().length > 0) return runtimeAgentId;
31
+ if (typeof fallback === "string" && fallback.trim().length > 0) return fallback;
32
+ return undefined;
33
+ }
34
+
29
35
  // ============================================================================
30
36
  // Utility Functions
31
37
  // ============================================================================
@@ -58,8 +64,10 @@ function sanitizeMemoryForSerialization(results: RetrievalResult[]) {
58
64
 
59
65
  export function registerMemoryRecallTool(api: OpenClawPluginApi, context: ToolContext) {
60
66
  api.registerTool(
61
- {
62
- name: "memory_recall",
67
+ (toolCtx) => {
68
+ const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main";
69
+ return {
70
+ name: "memory_recall",
63
71
  label: "Memory Recall",
64
72
  description: "Search through long-term memories using hybrid retrieval (vector + keyword search). Use when you need context about user preferences, past decisions, or previously discussed topics.",
65
73
  parameters: Type.Object({
@@ -80,9 +88,9 @@ export function registerMemoryRecallTool(api: OpenClawPluginApi, context: ToolCo
80
88
  const safeLimit = clampInt(limit, 1, 20);
81
89
 
82
90
  // Determine accessible scopes
83
- let scopeFilter = context.scopeManager.getAccessibleScopes(context.agentId);
91
+ let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
84
92
  if (scope) {
85
- if (context.scopeManager.isAccessible(scope, context.agentId)) {
93
+ if (context.scopeManager.isAccessible(scope, agentId)) {
86
94
  scopeFilter = [scope];
87
95
  } else {
88
96
  return {
@@ -134,6 +142,7 @@ export function registerMemoryRecallTool(api: OpenClawPluginApi, context: ToolCo
134
142
  };
135
143
  }
136
144
  },
145
+ };
137
146
  },
138
147
  { name: "memory_recall" }
139
148
  );
@@ -141,8 +150,10 @@ export function registerMemoryRecallTool(api: OpenClawPluginApi, context: ToolCo
141
150
 
142
151
  export function registerMemoryStoreTool(api: OpenClawPluginApi, context: ToolContext) {
143
152
  api.registerTool(
144
- {
145
- name: "memory_store",
153
+ (toolCtx) => {
154
+ const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main";
155
+ return {
156
+ name: "memory_store",
146
157
  label: "Memory Store",
147
158
  description: "Save important information in long-term memory. Use for preferences, facts, decisions, and other notable information.",
148
159
  parameters: Type.Object({
@@ -166,10 +177,10 @@ export function registerMemoryStoreTool(api: OpenClawPluginApi, context: ToolCon
166
177
 
167
178
  try {
168
179
  // Determine target scope
169
- let targetScope = scope || context.scopeManager.getDefaultScope(context.agentId);
180
+ let targetScope = scope || context.scopeManager.getDefaultScope(agentId);
170
181
 
171
182
  // Validate scope access
172
- if (!context.scopeManager.isAccessible(targetScope, context.agentId)) {
183
+ if (!context.scopeManager.isAccessible(targetScope, agentId)) {
173
184
  return {
174
185
  content: [{ type: "text", text: `Access denied to scope: ${targetScope}` }],
175
186
  details: { error: "scope_access_denied", requestedScope: targetScope },
@@ -233,6 +244,7 @@ export function registerMemoryStoreTool(api: OpenClawPluginApi, context: ToolCon
233
244
  };
234
245
  }
235
246
  },
247
+ };
236
248
  },
237
249
  { name: "memory_store" }
238
250
  );
@@ -240,8 +252,10 @@ export function registerMemoryStoreTool(api: OpenClawPluginApi, context: ToolCon
240
252
 
241
253
  export function registerMemoryForgetTool(api: OpenClawPluginApi, context: ToolContext) {
242
254
  api.registerTool(
243
- {
244
- name: "memory_forget",
255
+ (toolCtx) => {
256
+ const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main";
257
+ return {
258
+ name: "memory_forget",
245
259
  label: "Memory Forget",
246
260
  description: "Delete specific memories. Supports both search-based and direct ID-based deletion.",
247
261
  parameters: Type.Object({
@@ -258,9 +272,9 @@ export function registerMemoryForgetTool(api: OpenClawPluginApi, context: ToolCo
258
272
 
259
273
  try {
260
274
  // Determine accessible scopes
261
- let scopeFilter = context.scopeManager.getAccessibleScopes(context.agentId);
275
+ let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
262
276
  if (scope) {
263
- if (context.scopeManager.isAccessible(scope, context.agentId)) {
277
+ if (context.scopeManager.isAccessible(scope, agentId)) {
264
278
  scopeFilter = [scope];
265
279
  } else {
266
280
  return {
@@ -338,6 +352,7 @@ export function registerMemoryForgetTool(api: OpenClawPluginApi, context: ToolCo
338
352
  };
339
353
  }
340
354
  },
355
+ };
341
356
  },
342
357
  { name: "memory_forget" }
343
358
  );
@@ -349,8 +364,10 @@ export function registerMemoryForgetTool(api: OpenClawPluginApi, context: ToolCo
349
364
 
350
365
  export function registerMemoryUpdateTool(api: OpenClawPluginApi, context: ToolContext) {
351
366
  api.registerTool(
352
- {
353
- name: "memory_update",
367
+ (toolCtx) => {
368
+ const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main";
369
+ return {
370
+ name: "memory_update",
354
371
  label: "Memory Update",
355
372
  description: "Update an existing memory in-place. Preserves original timestamp. Use when correcting outdated info or adjusting importance/category without losing creation date.",
356
373
  parameters: Type.Object({
@@ -376,7 +393,7 @@ export function registerMemoryUpdateTool(api: OpenClawPluginApi, context: ToolCo
376
393
  }
377
394
 
378
395
  // Determine accessible scopes
379
- const scopeFilter = context.scopeManager.getAccessibleScopes(context.agentId);
396
+ const scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
380
397
 
381
398
  // Resolve memoryId: if it doesn't look like a UUID, try search
382
399
  let resolvedId = memoryId;
@@ -452,6 +469,7 @@ export function registerMemoryUpdateTool(api: OpenClawPluginApi, context: ToolCo
452
469
  };
453
470
  }
454
471
  },
472
+ };
455
473
  },
456
474
  { name: "memory_update" }
457
475
  );
@@ -463,8 +481,10 @@ export function registerMemoryUpdateTool(api: OpenClawPluginApi, context: ToolCo
463
481
 
464
482
  export function registerMemoryStatsTool(api: OpenClawPluginApi, context: ToolContext) {
465
483
  api.registerTool(
466
- {
467
- name: "memory_stats",
484
+ (toolCtx) => {
485
+ const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main";
486
+ return {
487
+ name: "memory_stats",
468
488
  label: "Memory Statistics",
469
489
  description: "Get statistics about memory usage, scopes, and categories.",
470
490
  parameters: Type.Object({
@@ -475,9 +495,9 @@ export function registerMemoryStatsTool(api: OpenClawPluginApi, context: ToolCon
475
495
 
476
496
  try {
477
497
  // Determine accessible scopes
478
- let scopeFilter = context.scopeManager.getAccessibleScopes(context.agentId);
498
+ let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
479
499
  if (scope) {
480
- if (context.scopeManager.isAccessible(scope, context.agentId)) {
500
+ if (context.scopeManager.isAccessible(scope, agentId)) {
481
501
  scopeFilter = [scope];
482
502
  } else {
483
503
  return {
@@ -524,6 +544,7 @@ export function registerMemoryStatsTool(api: OpenClawPluginApi, context: ToolCon
524
544
  };
525
545
  }
526
546
  },
547
+ };
527
548
  },
528
549
  { name: "memory_stats" }
529
550
  );
@@ -531,8 +552,10 @@ export function registerMemoryStatsTool(api: OpenClawPluginApi, context: ToolCon
531
552
 
532
553
  export function registerMemoryListTool(api: OpenClawPluginApi, context: ToolContext) {
533
554
  api.registerTool(
534
- {
535
- name: "memory_list",
555
+ (toolCtx) => {
556
+ const agentId = resolveAgentId((toolCtx as any)?.agentId, context.agentId) ?? "main";
557
+ return {
558
+ name: "memory_list",
536
559
  label: "Memory List",
537
560
  description: "List recent memories with optional filtering by scope and category.",
538
561
  parameters: Type.Object({
@@ -559,9 +582,9 @@ export function registerMemoryListTool(api: OpenClawPluginApi, context: ToolCont
559
582
  const safeOffset = clampInt(offset, 0, 1000);
560
583
 
561
584
  // Determine accessible scopes
562
- let scopeFilter = context.scopeManager.getAccessibleScopes(context.agentId);
585
+ let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
563
586
  if (scope) {
564
- if (context.scopeManager.isAccessible(scope, context.agentId)) {
587
+ if (context.scopeManager.isAccessible(scope, agentId)) {
565
588
  scopeFilter = [scope];
566
589
  } else {
567
590
  return {
@@ -609,6 +632,7 @@ export function registerMemoryListTool(api: OpenClawPluginApi, context: ToolCont
609
632
  };
610
633
  }
611
634
  },
635
+ };
612
636
  },
613
637
  { name: "memory_list" }
614
638
  );