mr-memory 2.17.0 → 2.18.1
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 +62 -8
- package/openclaw.plugin.json +5 -0
- 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");
|
|
@@ -363,7 +366,7 @@ const memoryRouterPlugin = {
|
|
|
363
366
|
messages: contextPayload,
|
|
364
367
|
session_id: ctx.sessionKey,
|
|
365
368
|
density,
|
|
366
|
-
|
|
369
|
+
...(embeddings && { embeddings }),
|
|
367
370
|
}),
|
|
368
371
|
});
|
|
369
372
|
|
|
@@ -475,7 +478,7 @@ const memoryRouterPlugin = {
|
|
|
475
478
|
messages: contextPayload,
|
|
476
479
|
session_id: ctx.sessionKey,
|
|
477
480
|
density,
|
|
478
|
-
|
|
481
|
+
...(embeddings && { embeddings }),
|
|
479
482
|
}),
|
|
480
483
|
});
|
|
481
484
|
|
|
@@ -594,6 +597,7 @@ const memoryRouterPlugin = {
|
|
|
594
597
|
messages: toStore,
|
|
595
598
|
session_id: ctx.sessionKey,
|
|
596
599
|
model: "unknown",
|
|
600
|
+
...(embeddings && { embeddings }),
|
|
597
601
|
}),
|
|
598
602
|
});
|
|
599
603
|
if (!res.ok) {
|
|
@@ -763,6 +767,48 @@ const memoryRouterPlugin = {
|
|
|
763
767
|
});
|
|
764
768
|
}
|
|
765
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
|
+
|
|
766
812
|
mr.command("status")
|
|
767
813
|
.description("Show MemoryRouter vault stats")
|
|
768
814
|
.option("--json", "JSON output")
|
|
@@ -780,12 +826,15 @@ const memoryRouterPlugin = {
|
|
|
780
826
|
return;
|
|
781
827
|
}
|
|
782
828
|
try {
|
|
783
|
-
const
|
|
829
|
+
const statsUrl = embeddings
|
|
830
|
+
? `${endpoint}/v1/memory/stats?embeddings=${encodeURIComponent(embeddings)}`
|
|
831
|
+
: `${endpoint}/v1/memory/stats`;
|
|
832
|
+
const res = await fetch(statsUrl, {
|
|
784
833
|
headers: { Authorization: `Bearer ${memoryKey}` },
|
|
785
834
|
});
|
|
786
835
|
const data = (await res.json()) as { totalVectors?: number; totalTokens?: number };
|
|
787
836
|
if (opts.json) {
|
|
788
|
-
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));
|
|
789
838
|
} else {
|
|
790
839
|
console.log("MemoryRouter Status");
|
|
791
840
|
console.log("───────────────────────────");
|
|
@@ -793,6 +842,7 @@ const memoryRouterPlugin = {
|
|
|
793
842
|
console.log(`Key: ${memoryKey.slice(0, 6)}...${memoryKey.slice(-3)}`);
|
|
794
843
|
console.log(`Mode: ${mode}`);
|
|
795
844
|
console.log(`Density: ${density}`);
|
|
845
|
+
console.log(`Embeddings: ${embeddings || "bge (default)"}`);
|
|
796
846
|
console.log(`Endpoint: ${endpoint}`);
|
|
797
847
|
console.log(`Memories: ${data.totalVectors ?? 0}`);
|
|
798
848
|
console.log(`Tokens: ${data.totalTokens ?? 0}`);
|
|
@@ -819,7 +869,7 @@ const memoryRouterPlugin = {
|
|
|
819
869
|
? path.resolve(configWorkspace.replace(/^~/, os.homedir()))
|
|
820
870
|
: path.join(os.homedir(), ".openclaw", "workspace");
|
|
821
871
|
const { runUpload } = await import("./upload.js");
|
|
822
|
-
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 });
|
|
823
873
|
});
|
|
824
874
|
|
|
825
875
|
mr.command("delete")
|
|
@@ -827,12 +877,16 @@ const memoryRouterPlugin = {
|
|
|
827
877
|
.action(async () => {
|
|
828
878
|
if (!memoryKey) { console.error("Not configured. Run: openclaw mr <key>"); return; }
|
|
829
879
|
try {
|
|
830
|
-
const
|
|
880
|
+
const deleteUrl = embeddings
|
|
881
|
+
? `${endpoint}/v1/memory?embeddings=${encodeURIComponent(embeddings)}`
|
|
882
|
+
: `${endpoint}/v1/memory`;
|
|
883
|
+
const res = await fetch(deleteUrl, {
|
|
831
884
|
method: "DELETE",
|
|
832
885
|
headers: { Authorization: `Bearer ${memoryKey}` },
|
|
833
886
|
});
|
|
834
887
|
const data = (await res.json()) as { message?: string };
|
|
835
|
-
|
|
888
|
+
const modelLabel = embeddings ? ` (${embeddings})` : "";
|
|
889
|
+
console.log(`✓ ${data.message || `Vault cleared${modelLabel}`}`);
|
|
836
890
|
} catch (err) {
|
|
837
891
|
console.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
838
892
|
}
|
package/openclaw.plugin.json
CHANGED
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
|
},
|