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.
- package/.github/ISSUE_TEMPLATE/bug_report.yml +81 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +57 -0
- package/CHANGELOG.md +12 -0
- package/README.md +36 -0
- package/README_CN.md +36 -0
- package/index.ts +13 -1
- package/package.json +1 -1
- package/src/store.ts +90 -2
- package/src/tools.ts +47 -23
|
@@ -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,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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
91
|
+
let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
|
|
84
92
|
if (scope) {
|
|
85
|
-
if (context.scopeManager.isAccessible(scope,
|
|
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
|
-
|
|
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(
|
|
180
|
+
let targetScope = scope || context.scopeManager.getDefaultScope(agentId);
|
|
170
181
|
|
|
171
182
|
// Validate scope access
|
|
172
|
-
if (!context.scopeManager.isAccessible(targetScope,
|
|
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
|
-
|
|
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(
|
|
275
|
+
let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
|
|
262
276
|
if (scope) {
|
|
263
|
-
if (context.scopeManager.isAccessible(scope,
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
498
|
+
let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
|
|
479
499
|
if (scope) {
|
|
480
|
-
if (context.scopeManager.isAccessible(scope,
|
|
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
|
-
|
|
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(
|
|
585
|
+
let scopeFilter = context.scopeManager.getAccessibleScopes(agentId);
|
|
563
586
|
if (scope) {
|
|
564
|
-
if (context.scopeManager.isAccessible(scope,
|
|
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
|
);
|