@xdarkicex/openclaw-memory-libravdb 1.4.17 → 1.4.19
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/README.md +2 -0
- package/cli-metadata.js +1 -0
- package/dist/cli-descriptors.d.ts +9 -0
- package/dist/cli-descriptors.js +18 -0
- package/dist/cli-metadata.d.ts +9 -0
- package/dist/cli-metadata.js +11 -0
- package/dist/cli.d.ts +2 -9
- package/dist/cli.js +192 -14
- package/dist/index.js +12 -4
- package/dist/memory-runtime.d.ts +6 -1
- package/dist/memory-runtime.js +13 -5
- package/docs/features.md +2 -0
- package/openclaw.plugin.json +6 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -118,6 +118,8 @@ Before exposing OpenClaw over remote channels, read [Security](./docs/security.m
|
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
120
|
openclaw memory status
|
|
121
|
+
openclaw memory index --force
|
|
122
|
+
openclaw memory search "prior context"
|
|
121
123
|
openclaw memory export --user-id <userId>
|
|
122
124
|
openclaw memory flush --user-id <userId>
|
|
123
125
|
openclaw memory journal --limit 50
|
package/cli-metadata.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./dist/cli-metadata.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
|
+
export declare const PLUGIN_ID = "libravdb-memory";
|
|
3
|
+
export declare const MEMORY_CLI_DESCRIPTOR: {
|
|
4
|
+
readonly name: "memory";
|
|
5
|
+
readonly description: "Manage LibraVDB memory";
|
|
6
|
+
readonly hasSubcommands: true;
|
|
7
|
+
};
|
|
8
|
+
export declare function isMemorySlotSelected(api: Pick<OpenClawPluginApi, "config">): boolean;
|
|
9
|
+
export declare function registerMemoryCliMetadata(api: Pick<OpenClawPluginApi, "config" | "registerCli">): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const PLUGIN_ID = "libravdb-memory";
|
|
2
|
+
export const MEMORY_CLI_DESCRIPTOR = {
|
|
3
|
+
name: "memory",
|
|
4
|
+
description: "Manage LibraVDB memory",
|
|
5
|
+
hasSubcommands: true,
|
|
6
|
+
};
|
|
7
|
+
export function isMemorySlotSelected(api) {
|
|
8
|
+
const slots = api.config?.plugins?.slots;
|
|
9
|
+
return slots?.memory === PLUGIN_ID;
|
|
10
|
+
}
|
|
11
|
+
export function registerMemoryCliMetadata(api) {
|
|
12
|
+
if (!isMemorySlotSelected(api)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
api.registerCli?.(() => { }, {
|
|
16
|
+
descriptors: [MEMORY_CLI_DESCRIPTOR],
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
kind?: "memory" | "context-engine" | Array<"memory" | "context-engine">;
|
|
6
|
+
configSchema?: unknown;
|
|
7
|
+
register(api: import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginApi): void | Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
|
+
import { PLUGIN_ID, registerMemoryCliMetadata } from "./cli-descriptors.js";
|
|
3
|
+
export default definePluginEntry({
|
|
4
|
+
id: PLUGIN_ID,
|
|
5
|
+
name: "LibraVDB Memory",
|
|
6
|
+
description: "Persistent vector memory with three-tier hybrid scoring",
|
|
7
|
+
kind: ["memory", "context-engine"],
|
|
8
|
+
register(api) {
|
|
9
|
+
registerMemoryCliMetadata(api);
|
|
10
|
+
},
|
|
11
|
+
});
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
2
|
import type { PluginRuntime } from "./plugin-runtime.js";
|
|
3
3
|
import type { LoggerLike, PluginConfig } from "./types.js";
|
|
4
|
-
type CliOptionBag = {
|
|
5
|
-
dreamFile?: string;
|
|
6
|
-
userId?: string;
|
|
7
|
-
sessionKey?: string;
|
|
8
|
-
sessionId?: string;
|
|
9
|
-
limit?: string | number;
|
|
10
|
-
yes?: boolean;
|
|
11
|
-
};
|
|
12
4
|
type CliCommand = {
|
|
13
5
|
commands?: CliCommand[];
|
|
14
6
|
command(name: string): CliCommand;
|
|
15
7
|
description(text: string): CliCommand;
|
|
8
|
+
argument?(name: string, description: string): CliCommand;
|
|
16
9
|
option(flags: string, description: string): CliCommand;
|
|
17
10
|
requiredOption?(flags: string, description: string): CliCommand;
|
|
18
|
-
action(handler: (
|
|
11
|
+
action(handler: (...args: unknown[]) => unknown): CliCommand;
|
|
19
12
|
name?(): string;
|
|
20
13
|
};
|
|
21
14
|
type CliProgram = CliCommand;
|
package/dist/cli.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { stdin, stdout } from "node:process";
|
|
3
|
+
import { MEMORY_CLI_DESCRIPTOR, isMemorySlotSelected } from "./cli-descriptors.js";
|
|
3
4
|
import { resolveDurableNamespace } from "./durable-namespace.js";
|
|
4
5
|
import { promoteDreamDiaryFile } from "./dream-promotion.js";
|
|
6
|
+
import { buildMemoryRuntimeBridge } from "./memory-runtime.js";
|
|
5
7
|
export function registerMemoryCli(api, runtime, cfg, logger = console) {
|
|
6
8
|
if (!api.registerCli) {
|
|
7
9
|
return;
|
|
8
10
|
}
|
|
11
|
+
if (!isMemorySlotSelected(api)) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
9
14
|
const isFullMode = runtime !== null;
|
|
10
15
|
api.registerCli(({ program }) => {
|
|
11
16
|
const root = ensureCommand(program, "memory")
|
|
12
17
|
.description("Manage LibraVDB memory");
|
|
13
18
|
if (!isFullMode) {
|
|
14
|
-
//
|
|
19
|
+
// Non-full modes register structure only so `openclaw memory --help` works.
|
|
15
20
|
// No runtime available — do not attach action handlers.
|
|
16
21
|
ensureCommand(root, "status").description("Show sidecar health, record counts, and active thresholds");
|
|
22
|
+
ensureCommand(root, "index").description("Refresh delegated LibraVDB memory index state");
|
|
23
|
+
ensureCommand(root, "search").description("Search LibraVDB memory");
|
|
17
24
|
ensureCommand(root, "flush").description("Wipe a durable memory namespace after confirmation");
|
|
18
25
|
ensureCommand(root, "export").description("Stream stored memories as newline-delimited JSON");
|
|
19
26
|
ensureCommand(root, "journal").description("Inspect internal lifecycle journal hints");
|
|
@@ -22,7 +29,40 @@ export function registerMemoryCli(api, runtime, cfg, logger = console) {
|
|
|
22
29
|
}
|
|
23
30
|
ensureCommand(root, "status")
|
|
24
31
|
.description("Show sidecar health, record counts, and active thresholds")
|
|
25
|
-
.
|
|
32
|
+
.option("--agent <id>", "Agent id")
|
|
33
|
+
.option("--json", "Print JSON")
|
|
34
|
+
.option("--deep", "Probe daemon readiness")
|
|
35
|
+
.option("--index", "Refresh delegated index state before printing status")
|
|
36
|
+
.option("--fix", "Accepted for OpenClaw memory CLI compatibility")
|
|
37
|
+
.option("--verbose", "Verbose logging")
|
|
38
|
+
.action(async (opts) => {
|
|
39
|
+
await runCliCommand(runtime, logger, async () => {
|
|
40
|
+
await runStatus(runtime, cfg, logger, normalizeOptionBag(opts));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
ensureCommand(root, "index")
|
|
44
|
+
.description("Refresh delegated LibraVDB memory index state")
|
|
45
|
+
.option("--agent <id>", "Agent id")
|
|
46
|
+
.option("--force", "Force refresh where supported")
|
|
47
|
+
.option("--verbose", "Verbose logging")
|
|
48
|
+
.action(async (opts) => {
|
|
49
|
+
await runCliCommand(runtime, logger, async () => {
|
|
50
|
+
await runIndex(runtime, cfg, normalizeOptionBag(opts), logger);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const search = ensureCommand(root, "search")
|
|
54
|
+
.description("Search LibraVDB memory")
|
|
55
|
+
.option("--query <text>", "Search query (alternative to positional argument)")
|
|
56
|
+
.option("--agent <id>", "Agent id")
|
|
57
|
+
.option("--max-results <n>", "Max results")
|
|
58
|
+
.option("--min-score <n>", "Minimum score")
|
|
59
|
+
.option("--json", "Print JSON");
|
|
60
|
+
search.argument?.("[query]", "Search query");
|
|
61
|
+
search.action(async (queryOrOpts, maybeOpts) => {
|
|
62
|
+
await runCliCommand(runtime, logger, async () => {
|
|
63
|
+
await runSearch(runtime, cfg, normalizeQueryArg(queryOrOpts), normalizeActionOptions(queryOrOpts, maybeOpts), logger);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
26
66
|
const flush = ensureCommand(root, "flush")
|
|
27
67
|
.description("Wipe a durable memory namespace after confirmation");
|
|
28
68
|
if (flush.requiredOption) {
|
|
@@ -34,17 +74,29 @@ export function registerMemoryCli(api, runtime, cfg, logger = console) {
|
|
|
34
74
|
flush.option("--session-key <sessionKey>", "Session key whose derived durable namespace should be deleted");
|
|
35
75
|
flush
|
|
36
76
|
.option("--yes", "Skip the confirmation prompt")
|
|
37
|
-
.action((opts) =>
|
|
77
|
+
.action(async (opts) => {
|
|
78
|
+
await runCliCommand(runtime, logger, async () => {
|
|
79
|
+
await runFlush(runtime, normalizeOptionBag(opts), logger);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
38
82
|
const exportCmd = ensureCommand(root, "export")
|
|
39
83
|
.description("Stream stored memories as newline-delimited JSON");
|
|
40
84
|
exportCmd.option("--user-id <userId>", "Restrict export to a single user namespace");
|
|
41
85
|
exportCmd.option("--session-key <sessionKey>", "Restrict export to a derived session-key namespace");
|
|
42
|
-
exportCmd.action((opts) =>
|
|
86
|
+
exportCmd.action(async (opts) => {
|
|
87
|
+
await runCliCommand(runtime, logger, async () => {
|
|
88
|
+
await runExport(runtime, normalizeOptionBag(opts), logger);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
43
91
|
const journal = ensureCommand(root, "journal")
|
|
44
92
|
.description("Inspect internal lifecycle journal hints");
|
|
45
93
|
journal.option("--session-id <sessionId>", "Restrict journal entries to one session id");
|
|
46
94
|
journal.option("--limit <limit>", "Maximum journal entries to show");
|
|
47
|
-
journal.action((opts) =>
|
|
95
|
+
journal.action(async (opts) => {
|
|
96
|
+
await runCliCommand(runtime, logger, async () => {
|
|
97
|
+
await runJournal(runtime, normalizeOptionBag(opts), logger);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
48
100
|
const dreamPromote = ensureCommand(root, "dream-promote")
|
|
49
101
|
.description("Promote vetted dream diary entries into the dedicated dream collection");
|
|
50
102
|
if (dreamPromote.requiredOption) {
|
|
@@ -55,15 +107,13 @@ export function registerMemoryCli(api, runtime, cfg, logger = console) {
|
|
|
55
107
|
dreamPromote.option("--user-id <userId>", "User id whose dream collection should receive the promotion");
|
|
56
108
|
dreamPromote.option("--dream-file <path>", "Dream diary markdown file to promote from");
|
|
57
109
|
}
|
|
58
|
-
dreamPromote.action((opts) =>
|
|
110
|
+
dreamPromote.action(async (opts) => {
|
|
111
|
+
await runCliCommand(runtime, logger, async () => {
|
|
112
|
+
await runDreamPromote(runtime, normalizeOptionBag(opts), logger);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
59
115
|
}, {
|
|
60
|
-
descriptors: [
|
|
61
|
-
{
|
|
62
|
-
name: "memory",
|
|
63
|
-
description: "Manage LibraVDB memory",
|
|
64
|
-
hasSubcommands: true,
|
|
65
|
-
},
|
|
66
|
-
],
|
|
116
|
+
descriptors: [MEMORY_CLI_DESCRIPTOR],
|
|
67
117
|
});
|
|
68
118
|
}
|
|
69
119
|
function ensureCommand(parent, name) {
|
|
@@ -78,10 +128,30 @@ function ensureCommand(parent, name) {
|
|
|
78
128
|
}
|
|
79
129
|
return parent.command(name);
|
|
80
130
|
}
|
|
81
|
-
async function
|
|
131
|
+
async function runCliCommand(runtime, logger, action) {
|
|
132
|
+
try {
|
|
133
|
+
await action();
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
try {
|
|
137
|
+
await runtime.shutdown();
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
logger.warn?.(`LibraVDB CLI shutdown failed: ${formatError(error)}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function runStatus(runtime, cfg, logger, opts = {}) {
|
|
145
|
+
if (opts.index) {
|
|
146
|
+
await runIndex(runtime, cfg, { ...opts, verbose: false }, logger, { quiet: true });
|
|
147
|
+
}
|
|
82
148
|
try {
|
|
83
149
|
const rpc = await runtime.getRpc();
|
|
84
150
|
const status = await rpc.call("status", {});
|
|
151
|
+
if (opts.json) {
|
|
152
|
+
console.log(JSON.stringify({ status }, null, 2));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
85
155
|
console.table({
|
|
86
156
|
Sidecar: status.ok ? "running" : "down",
|
|
87
157
|
"Turns stored": status.turnCount ?? 0,
|
|
@@ -95,6 +165,17 @@ async function runStatus(runtime, cfg, logger) {
|
|
|
95
165
|
}
|
|
96
166
|
catch (error) {
|
|
97
167
|
logger.error(`LibraVDB status unavailable: ${formatError(error)}`);
|
|
168
|
+
if (opts.json) {
|
|
169
|
+
console.log(JSON.stringify({
|
|
170
|
+
status: {
|
|
171
|
+
ok: false,
|
|
172
|
+
message: formatError(error),
|
|
173
|
+
gatingThreshold: cfg.ingestionGateThreshold ?? 0.35,
|
|
174
|
+
},
|
|
175
|
+
}, null, 2));
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
98
179
|
console.table({
|
|
99
180
|
Sidecar: "down",
|
|
100
181
|
"Turns stored": "n/a",
|
|
@@ -108,6 +189,79 @@ async function runStatus(runtime, cfg, logger) {
|
|
|
108
189
|
process.exitCode = 1;
|
|
109
190
|
}
|
|
110
191
|
}
|
|
192
|
+
async function runIndex(runtime, cfg, opts, logger, params = {}) {
|
|
193
|
+
try {
|
|
194
|
+
const bridge = buildMemoryRuntimeBridge(runtime.getRpc, cfg);
|
|
195
|
+
const { manager } = await bridge.getMemorySearchManager({
|
|
196
|
+
agentId: opts?.agent,
|
|
197
|
+
purpose: "status",
|
|
198
|
+
});
|
|
199
|
+
await manager.sync?.({
|
|
200
|
+
reason: "cli",
|
|
201
|
+
force: Boolean(opts?.force),
|
|
202
|
+
});
|
|
203
|
+
const status = manager.status();
|
|
204
|
+
if (status.ok === false) {
|
|
205
|
+
logger.error(`LibraVDB index refresh unavailable: ${status.message ?? "sidecar unavailable"}`);
|
|
206
|
+
process.exitCode = 1;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (opts?.verbose && !params.quiet) {
|
|
210
|
+
console.table({
|
|
211
|
+
Provider: status.provider ?? "libravdb",
|
|
212
|
+
Model: status.model ?? status.embeddingProfile ?? "unknown",
|
|
213
|
+
"Turns stored": status.turnCount ?? 0,
|
|
214
|
+
"Memories stored": status.memoryCount ?? 0,
|
|
215
|
+
Message: status.message ?? "ok",
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (!params.quiet) {
|
|
219
|
+
console.log("LibraVDB memory index refresh delegated to the sidecar.");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
logger.error(`LibraVDB index refresh failed: ${formatError(error)}`);
|
|
224
|
+
process.exitCode = 1;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function runSearch(runtime, cfg, queryArg, opts, logger) {
|
|
228
|
+
const query = opts?.query?.trim() || queryArg?.trim();
|
|
229
|
+
if (!query) {
|
|
230
|
+
logger.error("LibraVDB search requires a query. Provide a positional query or --query <text>.");
|
|
231
|
+
process.exitCode = 1;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
const bridge = buildMemoryRuntimeBridge(runtime.getRpc, cfg);
|
|
236
|
+
const { manager } = await bridge.getMemorySearchManager({
|
|
237
|
+
agentId: opts?.agent,
|
|
238
|
+
});
|
|
239
|
+
const maxResults = normalizeLimit(opts?.maxResults ?? opts?.limit);
|
|
240
|
+
const minScore = normalizeNumber(opts?.minScore);
|
|
241
|
+
const results = (await manager.search({
|
|
242
|
+
query,
|
|
243
|
+
...(maxResults ? { maxResults } : {}),
|
|
244
|
+
...(minScore !== undefined ? { minScore } : {}),
|
|
245
|
+
}));
|
|
246
|
+
if (opts?.json) {
|
|
247
|
+
console.log(JSON.stringify({ results }, null, 2));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (results.length === 0) {
|
|
251
|
+
console.log("No matches.");
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
for (const result of results) {
|
|
255
|
+
console.log(`${result.score.toFixed(3)} ${result.path}:${result.startLine}-${result.endLine}`);
|
|
256
|
+
console.log(result.snippet);
|
|
257
|
+
console.log("");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
logger.error(`LibraVDB search failed: ${formatError(error)}`);
|
|
262
|
+
process.exitCode = 1;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
111
265
|
async function runFlush(runtime, opts, logger) {
|
|
112
266
|
const namespace = resolveCliNamespace(opts);
|
|
113
267
|
if (!namespace) {
|
|
@@ -209,6 +363,30 @@ function normalizeLimit(limit) {
|
|
|
209
363
|
}
|
|
210
364
|
return undefined;
|
|
211
365
|
}
|
|
366
|
+
function normalizeNumber(value) {
|
|
367
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
368
|
+
return value;
|
|
369
|
+
}
|
|
370
|
+
if (typeof value === "string") {
|
|
371
|
+
const parsed = Number.parseFloat(value);
|
|
372
|
+
if (Number.isFinite(parsed)) {
|
|
373
|
+
return parsed;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return undefined;
|
|
377
|
+
}
|
|
378
|
+
function normalizeOptionBag(value) {
|
|
379
|
+
return value && typeof value === "object" ? value : {};
|
|
380
|
+
}
|
|
381
|
+
function normalizeActionOptions(queryOrOpts, maybeOpts) {
|
|
382
|
+
if (maybeOpts && typeof maybeOpts === "object") {
|
|
383
|
+
return maybeOpts;
|
|
384
|
+
}
|
|
385
|
+
return normalizeOptionBag(queryOrOpts);
|
|
386
|
+
}
|
|
387
|
+
function normalizeQueryArg(value) {
|
|
388
|
+
return typeof value === "string" ? value : undefined;
|
|
389
|
+
}
|
|
212
390
|
function resolveCliNamespace(opts) {
|
|
213
391
|
const userId = opts?.userId?.trim();
|
|
214
392
|
const sessionKey = opts?.sessionKey?.trim();
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
2
|
import { registerMemoryCli } from "./cli.js";
|
|
3
|
+
import { registerMemoryCliMetadata } from "./cli-descriptors.js";
|
|
3
4
|
import { buildContextEngineFactory } from "./context-engine.js";
|
|
4
5
|
import { createBeforeResetHook, createSessionEndHook } from "./lifecycle-hooks.js";
|
|
5
6
|
import { createDreamPromotionHandle } from "./dream-promotion.js";
|
|
@@ -10,10 +11,17 @@ import { createRecallCache } from "./recall-cache.js";
|
|
|
10
11
|
import { createPluginRuntime } from "./plugin-runtime.js";
|
|
11
12
|
export const MEMORY_ID = "libravdb-memory";
|
|
12
13
|
export function register(api) {
|
|
13
|
-
|
|
14
|
+
if (api.registrationMode === "cli-metadata") {
|
|
15
|
+
registerMemoryCliMetadata(api);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const mode = api.registrationMode;
|
|
19
|
+
const isFullMode = mode === "full";
|
|
14
20
|
const cfg = api.pluginConfig;
|
|
15
|
-
//
|
|
16
|
-
|
|
21
|
+
// OpenClaw lazy-loads plugin-owned CLI commands through discovery mode.
|
|
22
|
+
// Provide a runtime there so subcommands attach real handlers, but keep the
|
|
23
|
+
// long-lived memory/context-engine registrations gated to full mode only.
|
|
24
|
+
const runtimeOrNull = (isFullMode || mode === "discovery")
|
|
17
25
|
? createPluginRuntime(cfg, api.logger ?? console)
|
|
18
26
|
: null;
|
|
19
27
|
registerMemoryCli(api, runtimeOrNull, cfg, api.logger ?? console);
|
|
@@ -27,7 +35,7 @@ export function register(api) {
|
|
|
27
35
|
// Exclusive slot check: refuse to register if another plugin owns the memory slot.
|
|
28
36
|
// plugins.slots.memory is the only configurable slot; context engine exclusivity
|
|
29
37
|
// is enforced by the registry at runtime (no config surface for it).
|
|
30
|
-
// "none" means memory is disabled
|
|
38
|
+
// "none" means memory is disabled, not a conflict, allow registration.
|
|
31
39
|
const memSlot = api.config?.plugins?.slots?.memory;
|
|
32
40
|
if (memSlot && memSlot !== MEMORY_ID && memSlot !== "none") {
|
|
33
41
|
throw new Error(`[libravdb-memory] plugins.slots.memory is "${memSlot}". ` +
|
package/dist/memory-runtime.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ type MemorySearchParams = {
|
|
|
7
7
|
q?: string;
|
|
8
8
|
k?: number;
|
|
9
9
|
limit?: number;
|
|
10
|
+
maxResults?: number;
|
|
11
|
+
minScore?: number;
|
|
10
12
|
topK?: number;
|
|
11
13
|
userId?: string;
|
|
12
14
|
agentId?: string;
|
|
@@ -97,7 +99,10 @@ export declare function buildMemoryRuntimeBridge(getRpc: RpcGetter, cfg: PluginC
|
|
|
97
99
|
ingested: boolean;
|
|
98
100
|
delegatedToContextEngine: boolean;
|
|
99
101
|
}>;
|
|
100
|
-
sync(
|
|
102
|
+
sync(_params?: {
|
|
103
|
+
reason?: string;
|
|
104
|
+
force?: boolean;
|
|
105
|
+
}): Promise<{
|
|
101
106
|
synced: boolean;
|
|
102
107
|
delegatedToContextEngine: boolean;
|
|
103
108
|
}>;
|
package/dist/memory-runtime.js
CHANGED
|
@@ -26,7 +26,8 @@ function createMemorySearchManager(getRpc, cfg, defaults, initialStatus) {
|
|
|
26
26
|
const params = legacyCall
|
|
27
27
|
? {
|
|
28
28
|
query: queryOrParams,
|
|
29
|
-
limit: opts.limit ?? opts.k ?? opts.topK,
|
|
29
|
+
limit: opts.limit ?? opts.k ?? opts.maxResults ?? opts.topK,
|
|
30
|
+
minScore: opts.minScore,
|
|
30
31
|
sessionId: opts.sessionId,
|
|
31
32
|
sessionKey: opts.sessionKey,
|
|
32
33
|
userId: opts.userId,
|
|
@@ -46,7 +47,8 @@ function createMemorySearchManager(getRpc, cfg, defaults, initialStatus) {
|
|
|
46
47
|
agentId: firstString(params.agentId, params.context?.agentId, defaults.agentId),
|
|
47
48
|
fallback: sessionId ? `session:${sessionId}` : undefined,
|
|
48
49
|
});
|
|
49
|
-
const k = normalizePositiveInteger(params.k, params.limit, params.topK, cfg.topK, 8);
|
|
50
|
+
const k = normalizePositiveInteger(params.k, params.limit, params.maxResults, params.topK, cfg.topK, 8);
|
|
51
|
+
const minScore = normalizeNumber(params.minScore);
|
|
50
52
|
const rpc = await getRpc();
|
|
51
53
|
const result = dreamQuery.active
|
|
52
54
|
? await rpc.call("search_text", {
|
|
@@ -55,14 +57,17 @@ function createMemorySearchManager(getRpc, cfg, defaults, initialStatus) {
|
|
|
55
57
|
k,
|
|
56
58
|
})
|
|
57
59
|
: await searchResolvedCollections(rpc, cfg, userId, sessionId, queryText, k);
|
|
58
|
-
const
|
|
60
|
+
const filteredResults = minScore === undefined
|
|
61
|
+
? result.results
|
|
62
|
+
: result.results.filter((item) => item.score >= minScore);
|
|
63
|
+
const legacyResults = filteredResults.map((item) => ({
|
|
59
64
|
...item,
|
|
60
65
|
content: item.text,
|
|
61
66
|
}));
|
|
62
67
|
if (legacyCall) {
|
|
63
68
|
return { results: legacyResults };
|
|
64
69
|
}
|
|
65
|
-
return
|
|
70
|
+
return filteredResults.map(toMemorySearchResult);
|
|
66
71
|
},
|
|
67
72
|
async readFile(params) {
|
|
68
73
|
const located = await loadSearchResultText(getRpc, params.relPath);
|
|
@@ -79,7 +84,7 @@ function createMemorySearchManager(getRpc, cfg, defaults, initialStatus) {
|
|
|
79
84
|
// The plugin already owns per-turn ingest through the context engine.
|
|
80
85
|
return { ingested: false, delegatedToContextEngine: true };
|
|
81
86
|
},
|
|
82
|
-
async sync() {
|
|
87
|
+
async sync(_params) {
|
|
83
88
|
cachedStatus = await readStatus(getRpc, defaults.purpose);
|
|
84
89
|
return { synced: true, delegatedToContextEngine: true };
|
|
85
90
|
},
|
|
@@ -215,3 +220,6 @@ function normalizePositiveInteger(...values) {
|
|
|
215
220
|
}
|
|
216
221
|
return 8;
|
|
217
222
|
}
|
|
223
|
+
function normalizeNumber(value) {
|
|
224
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
225
|
+
}
|
package/docs/features.md
CHANGED
|
@@ -114,6 +114,8 @@ CLI API.
|
|
|
114
114
|
| Command | Purpose |
|
|
115
115
|
|---|---|
|
|
116
116
|
| `openclaw memory status` | Show sidecar health, counts, active thresholds, and model readiness. |
|
|
117
|
+
| `openclaw memory index --force` | Refresh delegated sidecar index state for OpenClaw memory CLI compatibility. |
|
|
118
|
+
| `openclaw memory search "query"` | Search LibraVDB memory through the active memory runtime bridge. |
|
|
117
119
|
| `openclaw memory export --user-id <userId>` | Stream stored memories as newline-delimited JSON for one durable namespace. |
|
|
118
120
|
| `openclaw memory export --session-key <sessionKey>` | Export a namespace derived from a session key. |
|
|
119
121
|
| `openclaw memory flush --user-id <userId>` | Delete one durable user namespace after confirmation. |
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
"id": "libravdb-memory",
|
|
3
3
|
"name": "LibraVDB Memory",
|
|
4
4
|
"description": "Persistent vector memory with three-tier hybrid scoring",
|
|
5
|
-
"version": "1.4.
|
|
5
|
+
"version": "1.4.19",
|
|
6
6
|
"kind": [
|
|
7
7
|
"memory",
|
|
8
8
|
"context-engine"
|
|
9
9
|
],
|
|
10
|
+
"activation": {
|
|
11
|
+
"onCommands": [
|
|
12
|
+
"memory"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
10
15
|
"configSchema": {
|
|
11
16
|
"type": "object",
|
|
12
17
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xdarkicex/openclaw-memory-libravdb",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"README.md",
|
|
21
21
|
"HOOK.md",
|
|
22
22
|
"index.js",
|
|
23
|
+
"cli-metadata.js",
|
|
23
24
|
"openclaw.plugin.json",
|
|
24
25
|
"package.json",
|
|
25
26
|
"docs/",
|