Skip to content

Commit d27803e

Browse files
voidfreudclaude
authored andcommitted
🐛 fix: fix OpenClaw plugin API compatibility with EverMemOS v1
The plugin was not working out of the box with the current EverMemOS API. Several request format mismatches caused 404, 405, 422, and fetch errors when used with OpenClaw. Fixes: 1. API version: /api/v0/ → /api/v1/ The plugin hardcoded /api/v0/ for both search and capture endpoints, but EverMemOS serves its API under /api/v1/. All requests returned 404. 2. Search field name: group_ids (array) → group_id (string) The plugin sent `group_ids: ["group-name"]` but the EverMemOS /memories/search endpoint expects `group_id: "group-name"` (a plain string). The array field was silently ignored, causing unscoped searches. 3. Capture role mapping: "tool" → "assistant" OpenClaw agent conversations include messages with role "tool" (tool call results). EverMemOS validates roles strictly and only accepts "user" or "assistant", returning HTTP 422 for any other value. Tool and system messages are now mapped to "assistant" since they are part of the assistant's workflow. 4. Search memory_types: array → comma-separated string The plugin sent memory_types as repeated query parameters (memory_types=a&memory_types=b). However, EverMemOS collects query params via dict(request.query_params) which flattens multi-value keys, keeping only the last value. The _parse_memory_types() function already supports comma-separated strings, so sending "a,b" works correctly. 5. README: fix example load.paths Changed the example path from "/path/to/EverMemOS-OpenClaw-Plugin" (wrong case, not a real path) to "~/.openclaw/extensions/evermemos- openclaw-plugin" which is the standard OpenClaw extensions directory. Note: OpenClaw resolves relative paths from the gateway process's working directory (process.cwd()), not from ~/.openclaw/, so using ~/ or absolute paths is required. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0f49826 commit d27803e

File tree

3 files changed

+10
-9
lines changed

3 files changed

+10
-9
lines changed

evermemos-openclaw-plugin/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Add the plugin directory to `plugins.load.paths` and enable it under `plugins.en
2525
"memory": "evermemos-openclaw-plugin"
2626
},
2727
"load": {
28-
"paths": ["/path/to/EverMemOS-OpenClaw-Plugin"]
28+
"paths": ["~/.openclaw/extensions/evermemos-openclaw-plugin"]
2929
},
3030
"entries": {
3131
"evermemos-openclaw-plugin": {

evermemos-openclaw-plugin/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default {
2828
const params = {
2929
query,
3030
user_id: cfg.userId,
31-
group_ids: cfg.groupId ? [cfg.groupId] : undefined,
31+
group_id: cfg.groupId || undefined,
3232
memory_types: cfg.memoryTypes,
3333
retrieve_method: cfg.retrieveMethod,
3434
top_k: cfg.topK,

evermemos-openclaw-plugin/src/memory-api.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ export async function searchMemories(cfg, params) {
1212

1313
const results = await Promise.all(
1414
searches.map(async ({ label, types }) => {
15-
const p = { ...baseParams, memory_types: types };
16-
console.log("[memory-api] GET /api/v0/memories/search", label, JSON.stringify(p));
17-
const r = await request(cfg, "GET", "/api/v0/memories/search", p);
15+
const p = { ...baseParams, memory_types: types.join(",") };
16+
console.log("[memory-api] GET /api/v1/memories/search", label, JSON.stringify(p));
17+
const r = await request(cfg, "GET", "/api/v1/memories/search", p);
1818
console.log("[memory-api] GET response", label, JSON.stringify(r));
1919
return r;
2020
}),
@@ -39,8 +39,9 @@ export async function saveMemories(cfg, { userId, groupId, messages = [], flush
3939
if (!messages.length) return;
4040
const stamp = Date.now();
4141
for (let i = 0; i < messages.length; i++) {
42-
const { role = "user", content = "", tool_calls, tool_call_id } = messages[i];
43-
const sender = role === "assistant" ? role : (role === "tool" ? "tool" : userId);
42+
const { role: rawRole = "user", content = "", tool_calls, tool_call_id } = messages[i];
43+
const role = rawRole === "user" ? "user" : "assistant";
44+
const sender = role === "assistant" ? role : userId;
4445
const isLast = i === messages.length - 1;
4546

4647
const payload = {
@@ -58,8 +59,8 @@ export async function saveMemories(cfg, { userId, groupId, messages = [], flush
5859
...(tool_call_id && { tool_call_id }),
5960
...(flush && isLast && { flush: true }),
6061
};
61-
console.log("[memory-api] POST /api/v0/memories", JSON.stringify(payload));
62-
const result = await request(cfg, "POST", "/api/v0/memories", payload);
62+
console.log("[memory-api] POST /api/v1/memories", JSON.stringify(payload));
63+
const result = await request(cfg, "POST", "/api/v1/memories", payload);
6364
console.log("[memory-api] POST response", JSON.stringify(result));
6465
}
6566
}

0 commit comments

Comments
 (0)