Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/MemOS-Cloud-OpenClaw-Plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ In `plugins.entries.memos-cloud-openclaw-plugin.config`:
- **Add** (`agent_end`)
- Builds a `/add/message` request with the **last turn** by default (user + assistant).
- Sends `messages` with `user_id`, `conversation_id`, and optional `tags/info/agent_id/app_id`.
- Cloud Hub rejects `info` keys named `local_state`, `state`, or `localStats` regardless of value; the plugin strips these reserved keys while preserving other custom `info` fields.
- Writes are asynchronous by default (`asyncMode: true`). For longer content, keep async mode enabled or increase `timeoutMs` if synchronous processing is explicitly configured.

## Multi-Agent Support
The plugin provides native support for multi-agent architectures (via the `agent_id` parameter):
Expand Down
2 changes: 2 additions & 0 deletions apps/MemOS-Cloud-OpenClaw-Plugin/README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ MEMOS_API_KEY=YOUR_TOKEN
- `user_id`、`conversation_id`
- `messages` 列表
- 可选 `tags / info / agent_id / app_id`
- Cloud Hub 当前会拒绝 `info` 中的 `local_state`、`state`、`localStats` 键(即使值不是 `null`);插件会自动剔除这些保留键,其他自定义 `info` 字段保持不变。
- 默认使用异步写入(`asyncMode: true`);切换为同步模式处理较长内容时,建议调高 `timeoutMs` 或继续使用异步模式。

## 多Agent支持(Multi-Agent)
插件内置对多Agent模式的支持(`agent_id` 参数):
Expand Down
6 changes: 5 additions & 1 deletion apps/MemOS-Cloud-OpenClaw-Plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,15 @@ export function buildAddMessagePayload(cfg, messages, ctx) {
if (cfg.appId) payload.app_id = cfg.appId;
if (cfg.tags?.length) payload.tags = cfg.tags;

const reservedInfoKeys = new Set(["local_state", "state", "localStats"]);
const customInfo = Object.fromEntries(
Object.entries(cfg.info || {}).filter(([key]) => !reservedInfoKeys.has(key)),
);
const info = {
source: MEMOS_SOURCE,
sessionKey: ctx?.sessionKey,
agentId: ctx?.agentId,
...(cfg.info || {}),
...customInfo,
};
if (Object.keys(info).length > 0) payload.info = info;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,34 @@ test("buildSearchPayload uses direct session id as user_id for private chats", (
assert.equal(payload.user_id, "1160853368999247882");
});

test("buildAddMessagePayload omits Cloud-reserved info keys", () => {
const cfg = {
userId: "openclaw-user",
tags: [],
info: {
local_state: {},
state: null,
localStats: "reserved",
channel: "webchat",
},
allowPublic: false,
allowKnowledgebaseIds: [],
asyncMode: true,
conversationId: "",
conversationIdPrefix: "",
conversationIdSuffix: "",
conversationSuffixMode: "none",
};

const payload = buildAddMessagePayload(cfg, [{ role: "user", content: "hi" }], {});

assert.equal(Object.hasOwn(payload.info, "local_state"), false);
assert.equal(Object.hasOwn(payload.info, "state"), false);
assert.equal(Object.hasOwn(payload.info, "localStats"), false);
assert.equal(payload.info.channel, "webchat");
assert.equal(payload.info.source, "openclaw_win");
});

test("buildAddMessagePayload keeps configured userId for non-direct chats", () => {
const cfg = {
userId: "openclaw-user",
Expand Down
Loading