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.
- package/index.ts +53 -1
- package/package.json +5 -1
- 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.
|
|
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
|
|
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) =>
|
|
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) =>
|
|
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];
|