mr-memory 1.0.8 → 1.0.10

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.
Files changed (3) hide show
  1. package/index.ts +53 -1
  2. package/package.json +5 -1
  3. package/upload.ts +31 -3
package/index.ts CHANGED
@@ -16,6 +16,7 @@ const DEFAULT_ENDPOINT = "https://api.memoryrouter.ai";
16
16
  type MemoryRouterConfig = {
17
17
  key: string;
18
18
  endpoint?: string;
19
+ density?: 'low' | 'high' | 'xhigh';
19
20
  };
20
21
 
21
22
  type CompatApi = OpenClawPluginApi & {
@@ -135,6 +136,7 @@ const memoryRouterPlugin = {
135
136
  const cfg = api.pluginConfig as MemoryRouterConfig | undefined;
136
137
  const endpoint = cfg?.endpoint?.replace(/\/v1\/?$/, "") || DEFAULT_ENDPOINT;
137
138
  const memoryKey = cfg?.key;
139
+ const density = cfg?.density || 'high';
138
140
 
139
141
  // ==================================================================
140
142
  // Core: Route LLM calls through MemoryRouter (only when key is set)
@@ -174,6 +176,7 @@ const memoryRouterPlugin = {
174
176
  ...options?.headers,
175
177
  "X-Memory-Key": memoryKey,
176
178
  "X-Memory-Store": toolIteration ? "false" : "true",
179
+ "X-Memory-Density": density,
177
180
  },
178
181
  };
179
182
 
@@ -240,6 +243,54 @@ const memoryRouterPlugin = {
240
243
  }
241
244
  });
242
245
 
246
+ // Density commands
247
+ mr.command("xhigh")
248
+ .description("Set memory density to xhigh (160 results, ~50k tokens)")
249
+ .action(async () => {
250
+ if (!memoryKey) {
251
+ console.error("MemoryRouter not configured. Run: openclaw mr <key>");
252
+ return;
253
+ }
254
+ try {
255
+ await setPluginConfig(api, { key: memoryKey, endpoint: cfg?.endpoint, density: 'xhigh' });
256
+ console.log("✓ Memory density set to xhigh (160 results, ~50k tokens)");
257
+ console.log(" Maximum context injection for deepest memory.");
258
+ } catch (err) {
259
+ console.error(`Failed to set density: ${err instanceof Error ? err.message : String(err)}`);
260
+ }
261
+ });
262
+
263
+ mr.command("high")
264
+ .description("Set memory density to high (80 results, ~24k tokens) [default]")
265
+ .action(async () => {
266
+ if (!memoryKey) {
267
+ console.error("MemoryRouter not configured. Run: openclaw mr <key>");
268
+ return;
269
+ }
270
+ try {
271
+ await setPluginConfig(api, { key: memoryKey, endpoint: cfg?.endpoint, density: 'high' });
272
+ console.log("✓ Memory density set to high (80 results, ~24k tokens)");
273
+ } catch (err) {
274
+ console.error(`Failed to set density: ${err instanceof Error ? err.message : String(err)}`);
275
+ }
276
+ });
277
+
278
+ mr.command("low")
279
+ .description("Set memory density to low (40 results, ~12k tokens)")
280
+ .action(async () => {
281
+ if (!memoryKey) {
282
+ console.error("MemoryRouter not configured. Run: openclaw mr <key>");
283
+ return;
284
+ }
285
+ try {
286
+ await setPluginConfig(api, { key: memoryKey, endpoint: cfg?.endpoint, density: 'low' });
287
+ console.log("✓ Memory density set to low (40 results, ~12k tokens)");
288
+ console.log(" Lighter context for faster responses or smaller models.");
289
+ } catch (err) {
290
+ console.error(`Failed to set density: ${err instanceof Error ? err.message : String(err)}`);
291
+ }
292
+ });
293
+
243
294
  mr.command("status")
244
295
  .description("Show MemoryRouter vault stats")
245
296
  .option("--json", "JSON output")
@@ -255,12 +306,13 @@ const memoryRouterPlugin = {
255
306
  const data = await res.json() as Record<string, unknown>;
256
307
 
257
308
  if (opts.json) {
258
- console.log(JSON.stringify({ enabled: true, key: memoryKey, stats: data }, null, 2));
309
+ console.log(JSON.stringify({ enabled: true, key: memoryKey, density, stats: data }, null, 2));
259
310
  } else {
260
311
  console.log("MemoryRouter Status");
261
312
  console.log("───────────────────────────");
262
313
  console.log(`Enabled: ✓ Yes`);
263
314
  console.log(`Key: ${memoryKey.slice(0, 6)}...${memoryKey.slice(-3)}`);
315
+ console.log(`Density: ${density} (openclaw mr xhigh|high|low)`);
264
316
  console.log(`Endpoint: ${endpoint}`);
265
317
  console.log("");
266
318
  console.log("Vault Stats:");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-memory",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "MemoryRouter persistent memory plugin for OpenClaw — your AI remembers every conversation",
5
5
  "type": "module",
6
6
  "files": [
@@ -26,6 +26,10 @@
26
26
  "directory": "integrations/openclaw-plugin"
27
27
  },
28
28
  "homepage": "https://memoryrouter.ai/openclaw",
29
+ "dependencies": {
30
+ "pdf-parse": "^1.1.1",
31
+ "mammoth": "^1.8.0"
32
+ },
29
33
  "openclaw": {
30
34
  "extensions": [
31
35
  "./index.ts"
package/upload.ts CHANGED
@@ -46,8 +46,30 @@ function chunkText(text: string, targetChars: number): string[] {
46
46
  return chunks;
47
47
  }
48
48
 
49
+ const BINARY_EXTENSIONS = new Set([".pdf", ".docx"]);
50
+ const DOC_EXTENSIONS = new Set([".md", ".pdf", ".docx"]);
51
+
52
+ async function extractText(filePath: string): Promise<string> {
53
+ const ext = path.extname(filePath).toLowerCase();
54
+ try {
55
+ if (ext === ".pdf") {
56
+ const pdfParse = (await import("pdf-parse")).default;
57
+ const buffer = await fs.readFile(filePath);
58
+ return (await pdfParse(buffer)).text;
59
+ }
60
+ if (ext === ".docx") {
61
+ const mammoth = await import("mammoth");
62
+ return (await mammoth.extractRawText({ path: filePath })).value;
63
+ }
64
+ } catch (err) {
65
+ console.error(` ⚠ Failed to extract ${path.basename(filePath)}: ${err instanceof Error ? err.message : err}`);
66
+ return "";
67
+ }
68
+ return fs.readFile(filePath, "utf-8");
69
+ }
70
+
49
71
  async function fileToJsonl(filePath: string): Promise<MemoryLine[]> {
50
- const content = await fs.readFile(filePath, "utf-8");
72
+ const content = await extractText(filePath);
51
73
  const stat = await fs.stat(filePath);
52
74
  const timestamp = Math.floor(stat.mtimeMs);
53
75
  const filename = path.basename(filePath);
@@ -127,7 +149,10 @@ async function discoverWorkspaceFiles(workspacePath: string): Promise<string[]>
127
149
  const memoryDir = path.join(workspacePath, "memory");
128
150
  if (await exists(memoryDir)) {
129
151
  const allMemFiles = await fs.readdir(memoryDir, { recursive: true });
130
- const mdFiles = (allMemFiles as string[]).filter((f) => f.endsWith(".md"));
152
+ const mdFiles = (allMemFiles as string[]).filter((f) => {
153
+ const ext = path.extname(f).toLowerCase();
154
+ return DOC_EXTENSIONS.has(ext);
155
+ });
131
156
  files.push(...mdFiles.map((f) => path.join(memoryDir, f)));
132
157
  }
133
158
 
@@ -201,7 +226,10 @@ export async function runUpload(params: {
201
226
  if (stat.isDirectory()) {
202
227
  const allDirFiles = await fs.readdir(resolved, { recursive: true });
203
228
  files = (allDirFiles as string[])
204
- .filter((f) => f.endsWith(".md") || f.endsWith(".jsonl"))
229
+ .filter((f) => {
230
+ const ext = path.extname(f).toLowerCase();
231
+ return DOC_EXTENSIONS.has(ext) || ext === ".jsonl";
232
+ })
205
233
  .map((f) => path.join(resolved, f));
206
234
  } else {
207
235
  files = [resolved];