mr-memory 3.3.0 → 3.5.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 +39 -8
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -271,6 +271,7 @@ type MemoryRouterConfig = {
|
|
|
271
271
|
mode?: "relay" | "proxy";
|
|
272
272
|
logging?: boolean;
|
|
273
273
|
embeddings?: string;
|
|
274
|
+
agentKeys?: Record<string, string>;
|
|
274
275
|
};
|
|
275
276
|
|
|
276
277
|
// ──────────────────────────────────────────────────────
|
|
@@ -380,10 +381,28 @@ const memoryRouterPlugin = {
|
|
|
380
381
|
const mode = cfg?.mode || "relay";
|
|
381
382
|
const logging = cfg?.logging ?? false;
|
|
382
383
|
const embeddings = cfg?.embeddings; // undefined = bge (default), "qwen" = qwen3-8b
|
|
384
|
+
const agentKeys = cfg?.agentKeys;
|
|
383
385
|
const log = (msg: string) => { if (logging) api.logger.info?.(msg); };
|
|
384
386
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
+
// Resolve the correct memory key for a given agent context.
|
|
388
|
+
// Multi-agent gateways: each agent gets its own key via agentKeys map.
|
|
389
|
+
// Single-agent: falls back to the global key.
|
|
390
|
+
function resolveKey(ctx: any): string | undefined {
|
|
391
|
+
if (agentKeys && ctx?.workspaceDir) {
|
|
392
|
+
// Derive agentId from workspace path: ~/.openclaw/workspace-rex → "rex"
|
|
393
|
+
// Default workspace (~/.openclaw/workspace) → "main"
|
|
394
|
+
const dirName = ctx.workspaceDir.split("/").pop() || "";
|
|
395
|
+
const agentId = dirName === "workspace" ? "main" : dirName.replace(/^workspace-/, "");
|
|
396
|
+
if (agentId && agentKeys[agentId]) return agentKeys[agentId];
|
|
397
|
+
}
|
|
398
|
+
return memoryKey;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const hasAnyKey = !!(memoryKey || (agentKeys && Object.keys(agentKeys).length > 0));
|
|
402
|
+
|
|
403
|
+
if (hasAnyKey) {
|
|
404
|
+
if (memoryKey) api.logger.info?.(`memoryrouter: active (key: ${memoryKey.slice(0, 6)}...)`);
|
|
405
|
+
if (agentKeys) api.logger.info?.(`memoryrouter: ${Object.keys(agentKeys).length} agent key(s) configured`);
|
|
387
406
|
} else {
|
|
388
407
|
api.logger.info?.("memoryrouter: no key configured — run: openclaw mr <key>");
|
|
389
408
|
api.logger.info?.("memoryrouter: get your free API key at https://memoryrouter.ai");
|
|
@@ -393,7 +412,7 @@ const memoryRouterPlugin = {
|
|
|
393
412
|
// Core: before_agent_start — search memories, inject context
|
|
394
413
|
// ==================================================================
|
|
395
414
|
|
|
396
|
-
if (
|
|
415
|
+
if (hasAnyKey) {
|
|
397
416
|
// Track whether we've already fired for this prompt (dedup double-fire)
|
|
398
417
|
let lastPreparedPrompt = "";
|
|
399
418
|
// Track whether before_prompt_build already handled the first call in this run
|
|
@@ -411,6 +430,9 @@ const memoryRouterPlugin = {
|
|
|
411
430
|
return;
|
|
412
431
|
}
|
|
413
432
|
|
|
433
|
+
const activeKey = resolveKey(ctx);
|
|
434
|
+
if (!activeKey) return; // No key for this agent
|
|
435
|
+
|
|
414
436
|
try {
|
|
415
437
|
const startMs = Date.now();
|
|
416
438
|
const prompt = event.prompt;
|
|
@@ -451,7 +473,7 @@ const memoryRouterPlugin = {
|
|
|
451
473
|
method: "POST",
|
|
452
474
|
headers: {
|
|
453
475
|
"Content-Type": "application/json",
|
|
454
|
-
Authorization: `Bearer ${
|
|
476
|
+
Authorization: `Bearer ${activeKey}`,
|
|
455
477
|
},
|
|
456
478
|
body: JSON.stringify({
|
|
457
479
|
messages: contextPayload,
|
|
@@ -491,6 +513,8 @@ const memoryRouterPlugin = {
|
|
|
491
513
|
// ── before_prompt_build: fires once per run (primary, includes full billing context)
|
|
492
514
|
api.on("before_prompt_build", async (event, ctx) => {
|
|
493
515
|
promptBuildFiredThisRun = true;
|
|
516
|
+
const activeKey = resolveKey(ctx);
|
|
517
|
+
if (!activeKey) return; // No key for this agent
|
|
494
518
|
try {
|
|
495
519
|
const startMs = Date.now();
|
|
496
520
|
const prompt = event.prompt;
|
|
@@ -561,7 +585,7 @@ const memoryRouterPlugin = {
|
|
|
561
585
|
method: "POST",
|
|
562
586
|
headers: {
|
|
563
587
|
"Content-Type": "application/json",
|
|
564
|
-
Authorization: `Bearer ${
|
|
588
|
+
Authorization: `Bearer ${activeKey}`,
|
|
565
589
|
},
|
|
566
590
|
body: JSON.stringify({
|
|
567
591
|
messages: contextPayload,
|
|
@@ -574,6 +598,9 @@ const memoryRouterPlugin = {
|
|
|
574
598
|
const errBody = await res.json().catch(() => null) as any;
|
|
575
599
|
if (errBody?.error?.code === "payment_required") {
|
|
576
600
|
api.logger.warn?.(`⚠️ MemoryRouter: Out of credits. Memory is NOT being injected. Add credits at https://app.memoryrouter.ai/settings/billing`);
|
|
601
|
+
return {
|
|
602
|
+
prependContext: "⚠️ MemoryRouter: This user's memory credits have run out. Memory is NOT active for this conversation. Let them know they need to add a payment method or top up their balance at https://app.memoryrouter.ai to restore memory."
|
|
603
|
+
};
|
|
577
604
|
} else {
|
|
578
605
|
log(`memoryrouter: prepare failed (${res.status})`);
|
|
579
606
|
}
|
|
@@ -605,6 +632,8 @@ const memoryRouterPlugin = {
|
|
|
605
632
|
// ==================================================================
|
|
606
633
|
|
|
607
634
|
api.on("agent_end", async (event, ctx) => {
|
|
635
|
+
const activeKey = resolveKey(ctx);
|
|
636
|
+
if (!activeKey) return; // No key for this agent
|
|
608
637
|
try {
|
|
609
638
|
const msgs = event.messages;
|
|
610
639
|
if (!msgs || !Array.isArray(msgs) || msgs.length === 0) return;
|
|
@@ -677,7 +706,7 @@ const memoryRouterPlugin = {
|
|
|
677
706
|
method: "POST",
|
|
678
707
|
headers: {
|
|
679
708
|
"Content-Type": "application/json",
|
|
680
|
-
Authorization: `Bearer ${
|
|
709
|
+
Authorization: `Bearer ${activeKey}`,
|
|
681
710
|
},
|
|
682
711
|
body: JSON.stringify({
|
|
683
712
|
messages: toStore,
|
|
@@ -711,6 +740,7 @@ const memoryRouterPlugin = {
|
|
|
711
740
|
|
|
712
741
|
// memory_search — calls MR /v1/memory/search
|
|
713
742
|
api.registerTool((ctx) => {
|
|
743
|
+
const toolKey = resolveKey(ctx);
|
|
714
744
|
return {
|
|
715
745
|
label: "Memory Search",
|
|
716
746
|
name: "memory_search",
|
|
@@ -725,6 +755,7 @@ const memoryRouterPlugin = {
|
|
|
725
755
|
required: ["query"],
|
|
726
756
|
} as any,
|
|
727
757
|
execute: async (_toolCallId: string, params: Record<string, unknown>) => {
|
|
758
|
+
if (!toolKey) return jsonToolResult({ results: [], error: "No memory key configured for this agent" });
|
|
728
759
|
const query = typeof params.query === "string" ? params.query.trim() : "";
|
|
729
760
|
if (!query) return jsonToolResult({ results: [], error: "query required" });
|
|
730
761
|
const limit = typeof params.maxResults === "number" ? params.maxResults : 50;
|
|
@@ -732,7 +763,7 @@ const memoryRouterPlugin = {
|
|
|
732
763
|
const res = await fetch(`${endpoint}/v1/memory/search`, {
|
|
733
764
|
method: "POST",
|
|
734
765
|
headers: {
|
|
735
|
-
Authorization: `Bearer ${
|
|
766
|
+
Authorization: `Bearer ${toolKey}`,
|
|
736
767
|
"Content-Type": "application/json",
|
|
737
768
|
...(embeddings && { "X-Embedding-Model": embeddings }),
|
|
738
769
|
},
|
|
@@ -807,7 +838,7 @@ const memoryRouterPlugin = {
|
|
|
807
838
|
},
|
|
808
839
|
};
|
|
809
840
|
});
|
|
810
|
-
} // end if (
|
|
841
|
+
} // end if (hasAnyKey)
|
|
811
842
|
|
|
812
843
|
// ==================================================================
|
|
813
844
|
// CLI Commands
|