mr-memory 2.16.0 → 2.18.0
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/index.ts +66 -8
- package/package.json +1 -1
- package/upload.ts +3 -1
package/index.ts
CHANGED
|
@@ -178,6 +178,7 @@ type MemoryRouterConfig = {
|
|
|
178
178
|
density?: "low" | "high" | "xhigh";
|
|
179
179
|
mode?: "relay" | "proxy";
|
|
180
180
|
logging?: boolean;
|
|
181
|
+
embeddings?: string;
|
|
181
182
|
};
|
|
182
183
|
|
|
183
184
|
// ──────────────────────────────────────────────────────
|
|
@@ -286,10 +287,12 @@ const memoryRouterPlugin = {
|
|
|
286
287
|
const density = cfg?.density || "high";
|
|
287
288
|
const mode = cfg?.mode || "relay";
|
|
288
289
|
const logging = cfg?.logging ?? false;
|
|
290
|
+
const embeddings = cfg?.embeddings; // undefined = bge (default), "qwen" = qwen3-8b
|
|
289
291
|
const log = (msg: string) => { if (logging) api.logger.info?.(msg); };
|
|
290
292
|
|
|
291
293
|
if (memoryKey) {
|
|
292
|
-
|
|
294
|
+
const modelLabel = embeddings ? `, embeddings: ${embeddings}` : "";
|
|
295
|
+
api.logger.info?.(`memoryrouter: active (key: ${memoryKey.slice(0, 6)}..., mode: ${mode}${modelLabel})`);
|
|
293
296
|
} else {
|
|
294
297
|
api.logger.info?.("memoryrouter: no key configured — run: openclaw mr <key>");
|
|
295
298
|
api.logger.info?.("memoryrouter: get your free API key at https://memoryrouter.ai");
|
|
@@ -329,6 +332,8 @@ const memoryRouterPlugin = {
|
|
|
329
332
|
for (const msg of event.historyMessages) {
|
|
330
333
|
const m = msg as { role?: string; content?: unknown };
|
|
331
334
|
if (!m.role) continue;
|
|
335
|
+
// Skip tool result/use messages — contains file reads, exec output, etc.
|
|
336
|
+
if (m.role !== "user" && m.role !== "assistant" && m.role !== "system") continue;
|
|
332
337
|
let text = "";
|
|
333
338
|
if (typeof m.content === "string") text = m.content;
|
|
334
339
|
else if (Array.isArray(m.content)) {
|
|
@@ -361,7 +366,7 @@ const memoryRouterPlugin = {
|
|
|
361
366
|
messages: contextPayload,
|
|
362
367
|
session_id: ctx.sessionKey,
|
|
363
368
|
density,
|
|
364
|
-
|
|
369
|
+
...(embeddings && { embeddings }),
|
|
365
370
|
}),
|
|
366
371
|
});
|
|
367
372
|
|
|
@@ -432,6 +437,8 @@ const memoryRouterPlugin = {
|
|
|
432
437
|
for (const msg of event.messages) {
|
|
433
438
|
const m = msg as { role?: string; content?: unknown };
|
|
434
439
|
if (!m.role) continue;
|
|
440
|
+
// Skip tool result/use messages — contains file reads, exec output, etc.
|
|
441
|
+
if (m.role !== "user" && m.role !== "assistant" && m.role !== "system") continue;
|
|
435
442
|
|
|
436
443
|
let text = "";
|
|
437
444
|
if (typeof m.content === "string") {
|
|
@@ -471,7 +478,7 @@ const memoryRouterPlugin = {
|
|
|
471
478
|
messages: contextPayload,
|
|
472
479
|
session_id: ctx.sessionKey,
|
|
473
480
|
density,
|
|
474
|
-
|
|
481
|
+
...(embeddings && { embeddings }),
|
|
475
482
|
}),
|
|
476
483
|
});
|
|
477
484
|
|
|
@@ -590,6 +597,7 @@ const memoryRouterPlugin = {
|
|
|
590
597
|
messages: toStore,
|
|
591
598
|
session_id: ctx.sessionKey,
|
|
592
599
|
model: "unknown",
|
|
600
|
+
...(embeddings && { embeddings }),
|
|
593
601
|
}),
|
|
594
602
|
});
|
|
595
603
|
if (!res.ok) {
|
|
@@ -759,6 +767,48 @@ const memoryRouterPlugin = {
|
|
|
759
767
|
});
|
|
760
768
|
}
|
|
761
769
|
|
|
770
|
+
// Embedding model command
|
|
771
|
+
mr.command("embeddings")
|
|
772
|
+
.description("Get or set embedding model (bge, qwen)")
|
|
773
|
+
.argument("[model]", "Embedding model: bge (default, 1024d) or qwen (4096d)")
|
|
774
|
+
.action(async (model: string | undefined) => {
|
|
775
|
+
if (!model) {
|
|
776
|
+
console.log(`Current embedding model: ${embeddings || "bge (default)"}`);
|
|
777
|
+
console.log(`\nAvailable models:`);
|
|
778
|
+
console.log(` bge BGE-M3 1024 dims (Cloudflare Workers AI, ~18ms, free)`);
|
|
779
|
+
console.log(` qwen Qwen3-8B 4096 dims (HuggingFace, ~69ms, $0.80/hr)`);
|
|
780
|
+
console.log(`\nUsage: openclaw mr embeddings <model>`);
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
const normalized = model.toLowerCase().trim();
|
|
784
|
+
const valid = ["bge", "bge-m3", "qwen", "qwen3", "qwen3-8b", "default"];
|
|
785
|
+
if (!valid.includes(normalized)) {
|
|
786
|
+
console.error(`Unknown model: "${model}". Valid options: bge, qwen`);
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (!memoryKey) { console.error("Not configured. Run: openclaw mr <key>"); return; }
|
|
790
|
+
// "bge" / "default" → clear embeddings (use server default)
|
|
791
|
+
const newEmbeddings = (normalized === "bge" || normalized === "bge-m3" || normalized === "default")
|
|
792
|
+
? undefined
|
|
793
|
+
: normalized.startsWith("qwen") ? "qwen" : normalized;
|
|
794
|
+
try {
|
|
795
|
+
await setPluginConfig(api, {
|
|
796
|
+
key: memoryKey,
|
|
797
|
+
endpoint: cfg?.endpoint,
|
|
798
|
+
density,
|
|
799
|
+
mode,
|
|
800
|
+
logging,
|
|
801
|
+
...(newEmbeddings && { embeddings: newEmbeddings }),
|
|
802
|
+
});
|
|
803
|
+
const label = newEmbeddings || "bge (default)";
|
|
804
|
+
console.log(`✓ Embedding model set to ${label}`);
|
|
805
|
+
console.log(` All future prepare/ingest/search will use ${label}`);
|
|
806
|
+
console.log(`\n Restart gateway to apply: openclaw gateway restart`);
|
|
807
|
+
} catch (err) {
|
|
808
|
+
console.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
|
|
762
812
|
mr.command("status")
|
|
763
813
|
.description("Show MemoryRouter vault stats")
|
|
764
814
|
.option("--json", "JSON output")
|
|
@@ -776,12 +826,15 @@ const memoryRouterPlugin = {
|
|
|
776
826
|
return;
|
|
777
827
|
}
|
|
778
828
|
try {
|
|
779
|
-
const
|
|
829
|
+
const statsUrl = embeddings
|
|
830
|
+
? `${endpoint}/v1/memory/stats?embeddings=${encodeURIComponent(embeddings)}`
|
|
831
|
+
: `${endpoint}/v1/memory/stats`;
|
|
832
|
+
const res = await fetch(statsUrl, {
|
|
780
833
|
headers: { Authorization: `Bearer ${memoryKey}` },
|
|
781
834
|
});
|
|
782
835
|
const data = (await res.json()) as { totalVectors?: number; totalTokens?: number };
|
|
783
836
|
if (opts.json) {
|
|
784
|
-
console.log(JSON.stringify({ enabled: true, key: memoryKey, density, mode, stats: data }, null, 2));
|
|
837
|
+
console.log(JSON.stringify({ enabled: true, key: memoryKey, density, mode, embeddings: embeddings || "bge", stats: data }, null, 2));
|
|
785
838
|
} else {
|
|
786
839
|
console.log("MemoryRouter Status");
|
|
787
840
|
console.log("───────────────────────────");
|
|
@@ -789,6 +842,7 @@ const memoryRouterPlugin = {
|
|
|
789
842
|
console.log(`Key: ${memoryKey.slice(0, 6)}...${memoryKey.slice(-3)}`);
|
|
790
843
|
console.log(`Mode: ${mode}`);
|
|
791
844
|
console.log(`Density: ${density}`);
|
|
845
|
+
console.log(`Embeddings: ${embeddings || "bge (default)"}`);
|
|
792
846
|
console.log(`Endpoint: ${endpoint}`);
|
|
793
847
|
console.log(`Memories: ${data.totalVectors ?? 0}`);
|
|
794
848
|
console.log(`Tokens: ${data.totalTokens ?? 0}`);
|
|
@@ -815,7 +869,7 @@ const memoryRouterPlugin = {
|
|
|
815
869
|
? path.resolve(configWorkspace.replace(/^~/, os.homedir()))
|
|
816
870
|
: path.join(os.homedir(), ".openclaw", "workspace");
|
|
817
871
|
const { runUpload } = await import("./upload.js");
|
|
818
|
-
await runUpload({ memoryKey, endpoint, targetPath, stateDir, workspacePath, hasWorkspaceFlag: !!opts.workspace, hasBrainFlag: !!opts.brain });
|
|
872
|
+
await runUpload({ memoryKey, endpoint, targetPath, stateDir, workspacePath, hasWorkspaceFlag: !!opts.workspace, hasBrainFlag: !!opts.brain, embeddings });
|
|
819
873
|
});
|
|
820
874
|
|
|
821
875
|
mr.command("delete")
|
|
@@ -823,12 +877,16 @@ const memoryRouterPlugin = {
|
|
|
823
877
|
.action(async () => {
|
|
824
878
|
if (!memoryKey) { console.error("Not configured. Run: openclaw mr <key>"); return; }
|
|
825
879
|
try {
|
|
826
|
-
const
|
|
880
|
+
const deleteUrl = embeddings
|
|
881
|
+
? `${endpoint}/v1/memory?embeddings=${encodeURIComponent(embeddings)}`
|
|
882
|
+
: `${endpoint}/v1/memory`;
|
|
883
|
+
const res = await fetch(deleteUrl, {
|
|
827
884
|
method: "DELETE",
|
|
828
885
|
headers: { Authorization: `Bearer ${memoryKey}` },
|
|
829
886
|
});
|
|
830
887
|
const data = (await res.json()) as { message?: string };
|
|
831
|
-
|
|
888
|
+
const modelLabel = embeddings ? ` (${embeddings})` : "";
|
|
889
|
+
console.log(`✓ ${data.message || `Vault cleared${modelLabel}`}`);
|
|
832
890
|
} catch (err) {
|
|
833
891
|
console.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
834
892
|
}
|
package/package.json
CHANGED
package/upload.ts
CHANGED
|
@@ -353,8 +353,9 @@ export async function runUpload(params: {
|
|
|
353
353
|
workspacePath?: string;
|
|
354
354
|
hasWorkspaceFlag?: boolean;
|
|
355
355
|
hasBrainFlag?: boolean;
|
|
356
|
+
embeddings?: string;
|
|
356
357
|
}): Promise<void> {
|
|
357
|
-
const { memoryKey, endpoint, targetPath, stateDir } = params;
|
|
358
|
+
const { memoryKey, endpoint, targetPath, stateDir, embeddings } = params;
|
|
358
359
|
const uploadUrl = `${endpoint}/v1/memory/upload`;
|
|
359
360
|
|
|
360
361
|
// Validate API reachability
|
|
@@ -469,6 +470,7 @@ export async function runUpload(params: {
|
|
|
469
470
|
headers: {
|
|
470
471
|
Authorization: `Bearer ${memoryKey}`,
|
|
471
472
|
"Content-Type": "text/plain",
|
|
473
|
+
...(embeddings && { "X-Embedding-Model": embeddings }),
|
|
472
474
|
},
|
|
473
475
|
body: jsonlBody,
|
|
474
476
|
},
|