mr-memory 1.0.5 → 1.0.7

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 CHANGED
@@ -13,8 +13,8 @@ openclaw plugins install mr-memory
13
13
  ## Setup
14
14
 
15
15
  ```bash
16
- openclaw mr enable <your-memory-key> # Get a key at memoryrouter.ai
17
- openclaw mr upload # Upload workspace + session history
16
+ openclaw mr <your-memory-key> # Get a key at memoryrouter.ai
17
+ openclaw mr upload # Upload workspace + session history
18
18
  ```
19
19
 
20
20
  ## Commands
@@ -25,7 +25,7 @@ openclaw mr upload # Upload workspace + sessions
25
25
  openclaw mr upload --brain ~/.notopenclaw # Upload from a different agent
26
26
  openclaw mr off # Disable
27
27
  openclaw mr delete # Clear vault
28
- openclaw mr enable <key> # Enable with key
28
+ openclaw mr <key> # Enable with key
29
29
  ```
30
30
 
31
31
  ## Upload Options
@@ -44,7 +44,7 @@ Only direct user-to-AI conversation is stored. Tool use and subagent work are ex
44
44
 
45
45
  ## Config
46
46
 
47
- After `openclaw mr enable <key>`, config is stored at:
47
+ After `openclaw mr <key>`, config is stored at:
48
48
 
49
49
  ```json
50
50
  {
package/index.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  * BYOK — provider API keys pass through untouched.
9
9
  */
10
10
 
11
+ import { spawn } from "node:child_process";
11
12
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
12
13
 
13
14
  const DEFAULT_ENDPOINT = "https://api.memoryrouter.ai";
@@ -17,6 +18,11 @@ type MemoryRouterConfig = {
17
18
  endpoint?: string;
18
19
  };
19
20
 
21
+ type CompatApi = OpenClawPluginApi & {
22
+ updatePluginConfig?: (config: Record<string, unknown>) => Promise<void>;
23
+ updatePluginEnabled?: (enabled: boolean) => Promise<void>;
24
+ };
25
+
20
26
  /**
21
27
  * Supported provider APIs that MemoryRouter can proxy.
22
28
  */
@@ -56,6 +62,70 @@ function isToolUseIteration(context: { messages?: Array<{ role: string; content?
56
62
  return false;
57
63
  }
58
64
 
65
+ function resolveOpenClawInvocation(): { command: string; args: string[] } {
66
+ const entry = process.argv[1];
67
+ if (entry) {
68
+ return {
69
+ command: process.execPath,
70
+ args: [entry],
71
+ };
72
+ }
73
+
74
+ return {
75
+ command: "openclaw",
76
+ args: [],
77
+ };
78
+ }
79
+
80
+ async function runOpenClawConfigSet(path: string, value: string, json = false): Promise<void> {
81
+ const base = resolveOpenClawInvocation();
82
+ const args = [...base.args, "config", "set", path, value];
83
+ if (json) {
84
+ args.push("--json");
85
+ }
86
+
87
+ await new Promise<void>((resolve, reject) => {
88
+ const child = spawn(base.command, args, {
89
+ stdio: ["ignore", "ignore", "pipe"],
90
+ env: process.env,
91
+ });
92
+
93
+ let stderr = "";
94
+ child.stderr.on("data", (chunk) => {
95
+ stderr += String(chunk);
96
+ });
97
+
98
+ child.on("error", (err) => reject(err));
99
+ child.on("close", (code) => {
100
+ if (code === 0) {
101
+ resolve();
102
+ return;
103
+ }
104
+ reject(new Error(`openclaw config set failed (exit ${code}): ${stderr.trim()}`));
105
+ });
106
+ });
107
+ }
108
+
109
+ async function setPluginConfig(api: OpenClawPluginApi, config: Record<string, unknown>): Promise<void> {
110
+ const compat = api as CompatApi;
111
+ if (typeof compat.updatePluginConfig === "function") {
112
+ await compat.updatePluginConfig(config);
113
+ return;
114
+ }
115
+
116
+ await runOpenClawConfigSet(`plugins.entries.${api.id}.config`, JSON.stringify(config), true);
117
+ }
118
+
119
+ async function setPluginEnabled(api: OpenClawPluginApi, enabled: boolean): Promise<void> {
120
+ const compat = api as CompatApi;
121
+ if (typeof compat.updatePluginEnabled === "function") {
122
+ await compat.updatePluginEnabled(enabled);
123
+ return;
124
+ }
125
+
126
+ await runOpenClawConfigSet(`plugins.entries.${api.id}.enabled`, enabled ? "true" : "false", true);
127
+ }
128
+
59
129
  const memoryRouterPlugin = {
60
130
  id: "mr-memory",
61
131
  name: "MemoryRouter",
@@ -118,6 +188,25 @@ const memoryRouterPlugin = {
118
188
 
119
189
  api.registerCli(
120
190
  ({ program }) => {
191
+ const applyKey = async (key: string) => {
192
+ if (!key.startsWith("mk")) {
193
+ console.error("Invalid key format. Keys start with 'mk' (e.g. mk_xxx)");
194
+ return;
195
+ }
196
+
197
+ try {
198
+ await setPluginConfig(api, { key });
199
+ await setPluginEnabled(api, true);
200
+ console.log(`✓ MemoryRouter enabled. Key: ${key.slice(0, 6)}...${key.slice(-3)}`);
201
+ console.log(`\nRun: openclaw mr upload to upload your memories`);
202
+ } catch (err) {
203
+ const message = err instanceof Error ? err.message : String(err);
204
+ console.error(`Failed to enable MemoryRouter: ${message}`);
205
+ console.error("Fallback: openclaw config set plugins.entries.mr-memory.config.key <key>");
206
+ console.error("Then: openclaw config set plugins.entries.mr-memory.enabled true --json");
207
+ }
208
+ };
209
+
121
210
  const mr = program.command("mr")
122
211
  .description("MemoryRouter memory commands")
123
212
  .argument("[key]", "Your MemoryRouter memory key (mk_xxx)")
@@ -127,14 +216,7 @@ const memoryRouterPlugin = {
127
216
  mr.help();
128
217
  return;
129
218
  }
130
- if (!key.startsWith("mk")) {
131
- console.error("Invalid key format. Keys start with 'mk' (e.g. mk_xxx)");
132
- return;
133
- }
134
- await api.updatePluginConfig({ key });
135
- await api.updatePluginEnabled(true);
136
- console.log(`✓ MemoryRouter enabled. Key: ${key.slice(0, 6)}...${key.slice(-3)}`);
137
- console.log(`\nRun: openclaw mr upload to upload your memories`);
219
+ await applyKey(key);
138
220
  });
139
221
 
140
222
  // Backward compat: `openclaw mr enable <key>` still works
@@ -142,22 +224,20 @@ const memoryRouterPlugin = {
142
224
  .description("Enable MemoryRouter with a memory key (alias)")
143
225
  .argument("<key>", "Your MemoryRouter memory key (mk_xxx)")
144
226
  .action(async (key: string) => {
145
- if (!key.startsWith("mk")) {
146
- console.error("Invalid key format. Keys start with 'mk' (e.g. mk_xxx)");
147
- return;
148
- }
149
- await api.updatePluginConfig({ key });
150
- await api.updatePluginEnabled(true);
151
- console.log(`✓ MemoryRouter enabled. Key: ${key.slice(0, 6)}...${key.slice(-3)}`);
152
- console.log(`\nRun: openclaw mr upload to upload your memories`);
227
+ await applyKey(key);
153
228
  });
154
229
 
155
230
  mr.command("off")
156
231
  .description("Disable MemoryRouter (removes key)")
157
232
  .action(async () => {
158
- await api.updatePluginConfig({});
159
- console.log("✓ MemoryRouter disabled. LLM calls go direct to provider.");
160
- console.log(" Key removed. Re-enable with: openclaw mr <key>");
233
+ try {
234
+ await setPluginConfig(api, {});
235
+ await setPluginEnabled(api, false);
236
+ console.log("✓ MemoryRouter disabled. LLM calls go direct to provider.");
237
+ console.log(" Key removed. Re-enable with: openclaw mr <key>");
238
+ } catch (err) {
239
+ console.error(`Failed to disable MemoryRouter: ${err instanceof Error ? err.message : String(err)}`);
240
+ }
161
241
  });
162
242
 
163
243
  mr.command("status")
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-memory",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "MemoryRouter persistent memory plugin for OpenClaw — your AI remembers every conversation",
5
5
  "type": "module",
6
6
  "keywords": [