Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules/
.pnpm-store/
dist/
lib/
*.log
.env
.DS_Store
Expand Down
59 changes: 43 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# OpenClaw Memory (PowerMem) Plugin

This plugin lets [OpenClaw](https://github.com/openclaw/openclaw) use long-term memory via [PowerMem](https://github.com/oceanbase/powermem): intelligent extraction, Ebbinghaus forgetting curve, multi-agent isolation.
This plugin lets [OpenClaw](https://github.com/openclaw/openclaw) use long-term memory via [PowerMem](https://github.com/oceanbase/powermem): intelligent extraction, Ebbinghaus forgetting curve, multi-agent isolation. Supports HTTP v2 (per-request config + agent memory sharing), LLM-based experience extraction, and optional dual-write to local SQLite.

**Default:** **CLI mode** — the plugin runs `pmem` locally (no `powermem-server`). Use **HTTP mode** when you already run a shared PowerMem API (teams / enterprise).

Expand Down Expand Up @@ -185,13 +185,13 @@ openclaw plugins install -l /path/to/memory-powermem

**Note:** Running `npm i memory-powermem` in a Node project only adds the package to that project’s `node_modules`; it does **not** register the plugin with OpenClaw. To use this as an OpenClaw plugin, you must run `openclaw plugins install memory-powermem` (or install from a path as above), then restart the gateway.

After install, run `openclaw plugins list` and confirm `memory-powermem` is listed. With **no** `plugins.entries["memory-powermem"].config`, the plugin uses **defaults**: `mode: "cli"`, `envFile` under `~/.openclaw/powermem/powermem.env`, `pmemPath: "pmem"`, plus `autoCapture` / `autoRecall` / `inferOnAdd` enabled. Ensure `pmem` is on PATH (or set `pmemPath`) and the env file exists and is valid.
After install, run `openclaw plugins list` and confirm `memory-powermem` is listed. With **no** `plugins.entries["memory-powermem"].config`, the plugin uses **defaults**: `mode: "cli"`, `pmemPath: "bundled"` (npm `powermem` from plugin dependencies), `useOpenClawModel: true` (SQLite under OpenClaw state + LLM from `agents.defaults.model`), plus `autoCapture` / `autoRecall` / `inferOnAdd` enabled. No separate `powermem.env` is required unless you opt out of OpenClaw model injection.

---

## Step 3: Configure OpenClaw (optional)

If you use **CLI mode** with the default paths and `pmem` on PATH, you can skip this step. Customize for HTTP, a different URL/API key, or a non-default `envFile` / `pmemPath`.
If you use **CLI mode** with defaults (`bundled` + OpenClaw model injection), you can skip this step. Customize for HTTP, a different URL/API key, Python `pmem` (`pmemPath: "auto"` or an absolute path), or a `powermem` `.env` via `envFile`.

**CLI (default):**

Expand All @@ -205,7 +205,7 @@ If you use **CLI mode** with the default paths and `pmem` on PATH, you can skip
"config": {
"mode": "cli",
"envFile": "/home/you/.openclaw/powermem/powermem.env",
"pmemPath": "pmem",
"pmemPath": "bundled",
"autoCapture": true,
"autoRecall": true,
"inferOnAdd": true
Expand All @@ -222,15 +222,19 @@ If you use **CLI mode** with the default paths and `pmem` on PATH, you can skip
"config": {
"mode": "http",
"baseUrl": "http://localhost:8000",
"httpApiVersion": "v2",
"requestConfig": { "memory_db": { "host": "db-host", "port": 2881 } },
"autoCapture": true,
"autoRecall": true,
"autoExperience": true,
"experienceRecall": true,
"inferOnAdd": true
}
```

Notes:

- **CLI (default):** You may omit `mode` and use CLI when `baseUrl` is empty; use `envFile` + `pmemPath`.
- **CLI (default):** You may omit `mode` and use CLI when `baseUrl` is empty. Default `pmemPath` is `bundled` (npm CLI). Use `envFile` and/or `pmemPath` when you need a custom setup.
- **HTTP:** When `mode` is `http`, `baseUrl` is required; if you set `baseUrl` without `mode`, the plugin treats it as HTTP. Do **not** append `/api/v1` to `baseUrl`. If the server uses API key auth, add `"apiKey"`.
- **Restart the OpenClaw gateway** (or Mac menubar app) after changing config.

Expand Down Expand Up @@ -283,16 +287,32 @@ After installing, uninstalling, or changing config, restart the OpenClaw gateway

| Option | Required | Description |
|---------------|----------|-------------|
| `mode` | No | Backend: `"cli"` (default) or `"http"`. If omitted, non-empty `baseUrl` implies `http`. |
| `baseUrl` | Yes (http) | PowerMem API base URL when `mode` is `http`, e.g. `http://localhost:8000`, no `/api/v1` suffix. |
| `apiKey` | No | Set when PowerMem server has API key authentication enabled (http mode). |
| `envFile` | No | CLI: path to PowerMem `.env` (default when using plugin defaults: `~/.openclaw/powermem/powermem.env`). |
| `pmemPath` | No | CLI: path to `pmem` executable; default `pmem`. |
| `userId` | No | User isolation (multi-user); default `openclaw-user`. |
| `agentId` | No | Agent isolation (multi-agent); default `openclaw-agent`. |
| `autoCapture` | No | Auto-store from conversations after agent ends; default `true`. |
| `autoRecall` | No | Auto-inject relevant memories before agent starts; default `true`. |
| `inferOnAdd` | No | Use PowerMem intelligent extraction when adding; default `true`. |
| `mode` | No | Backend: `"cli"` (default) or `"http"`. If omitted, non-empty `baseUrl` implies `http`. |
| `baseUrl` | Yes (http) | PowerMem API base URL when `mode` is `http`, e.g. `http://localhost:8000`, no `/api/v1` suffix. |
| `apiKey` | No | Set when PowerMem server has API key authentication enabled (http mode). |
| `httpApiVersion` | No | HTTP API version: `"v1"` (default) or `"v2"`. |
| `requestConfig` | No | HTTP v2 only: forwarded as `config` in each request (e.g. `memory_db` settings). |
| `envFile` | No | CLI: path to PowerMem `.env` (default when using plugin defaults: `~/.openclaw/powermem/powermem.env`). |
| `pmemPath` | No | CLI: `bundled` (default), `auto`, or path/command for `pmem`. |
| `userId` | No | User isolation (multi-user). If omitted or set to `"auto"`, a stable ID is generated and stored in `<stateDir>/powermem/identity.json`. |
| `agentId` | No | Agent isolation (multi-agent). If omitted or set to `"auto"`, a stable ID is generated and stored in `<stateDir>/powermem/identity.json`. |
| `autoCapture` | No | Auto-store from conversations after agent ends; default `true`. |
| `autoRecall` | No | Auto-inject relevant memories before agent starts; default `true`. |
| `autoExperience` | No | Auto-extract procedural experiences via LLM; default `true`. |
| `experienceRecall` | No | Include experiences in recall results; default `true`. |
| `inferOnAdd` | No | Use PowerMem intelligent extraction when adding; default `true`. |
| `dualWrite` | No | HTTP only: write to remote + local SQLite and queue failed writes. |
| `localDbPath` | No | Local SQLite path for `dualWrite`. |
| `localUserId` | No | Local namespace for `dualWrite` (defaults to `userId`). |
| `localAgentId` | No | Local namespace for `dualWrite` (defaults to `agentId`). |
| `syncOnResume` | No | Whether to sync pending writes on startup; default `true`. |
| `syncBatchSize` | No | Pending sync batch size; default `50`. |
| `syncMinIntervalMs` | No | Minimum interval between sync attempts; default `5000`. |
| `syncBaseDelayMs` | No | Base delay for retry backoff; default `5000`. |
| `syncMaxDelayMs` | No | Max delay for retry backoff; default `60000`. |
| `syncMaxRetries` | No | Max retry count per pending item; default `10`. |

**Memory partitioning and sharing:** Use `userId` / `agentId` for logical isolation. In HTTP v2, `agent_memory_share` supports cross-agent sharing within the same `userId`; use `cross_scope_share` when you need to copy memories across both `userId` and `agentId` scopes.

**Auto-capture:** When a session ends, this round’s user/assistant text is sent to PowerMem (`infer: true`) for extraction and storage. At most 3 items per round, each up to about 6000 characters.

Expand All @@ -305,6 +325,13 @@ Exposed to OpenClaw agents:
- **memory_recall** — Search long-term memories by query.
- **memory_store** — Store one memory (optional intelligent extraction on write).
- **memory_forget** — Delete by memory ID or by search query.
- **experience_store** — Store a procedural experience.
- **experience_recall** — Search stored experiences.
- **agent_memory_add** — Add memory to another agent (HTTP v2 only).
- **agent_memory_list** — List an agent’s memories (HTTP v2 only).
- **agent_memory_share** — Share memories across agents (HTTP v2 only).
- **agent_memory_shared** — List memories shared with an agent (HTTP v2 only).
- **cross_scope_share** — Copy memories across `userId`/`agentId` scopes (HTTP v2 only). Parameters: `fromUserId`, `fromAgentId`, `toUserId`, `toAgentId`, `query`; optional `limit`, `scoreThreshold`, `inferOnTarget`.

---

Expand All @@ -320,7 +347,7 @@ Exposed to OpenClaw agents:

**1. `openclaw ltm health` fails or cannot connect**

- **CLI:** `pmem` on PATH or correct `pmemPath`; valid `.env` at `envFile`.
- **CLI:** npm `powermem` installed with the plugin (`bundled`), or correct `pmemPath`; optional `.env` at `envFile` if not using OpenClaw model injection.
- **HTTP:** PowerMem is running (HTTP server in a terminal, or Docker); `baseUrl` is correct (e.g. `http://localhost:8000`; watch for `127.0.0.1` vs `localhost` mismatches).
- Remote server: use the host IP or hostname instead of `localhost`.

Expand Down
59 changes: 43 additions & 16 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# OpenClaw Memory (PowerMem) 插件

本插件让 [OpenClaw](https://github.com/openclaw/openclaw) 通过 [PowerMem](https://github.com/oceanbase/powermem) 使用长期记忆:智能抽取、艾宾浩斯遗忘曲线、多 Agent 隔离。
本插件让 [OpenClaw](https://github.com/openclaw/openclaw) 通过 [PowerMem](https://github.com/oceanbase/powermem) 使用长期记忆:智能抽取、艾宾浩斯遗忘曲线、多 Agent 隔离。支持 HTTP v2(按请求配置 + 代理共享)、LLM 经验提炼与本地 SQLite 双写。

**默认:CLI 模式** — 插件在本机执行 `pmem`,无需 `powermem-server`。**HTTP 模式** 适合已有共享 PowerMem API 的场景(团队 / 企业)。

Expand Down Expand Up @@ -186,13 +186,13 @@ openclaw plugins install -l /path/to/memory-powermem

**说明:** 在某个 Node 项目里执行 `npm i memory-powermem` 只会把包装进该项目的 `node_modules`,**不会**在 OpenClaw 里注册插件。若要在 OpenClaw 里使用本插件,必须执行 `openclaw plugins install memory-powermem`(或按上面用本地路径安装),再重启 gateway。

安装成功后,可用 `openclaw plugins list` 确认能看到 `memory-powermem`。若未写 `plugins.entries["memory-powermem"].config`,插件 **默认**:`mode: "cli"`、`envFile` 为 `~/.openclaw/powermem/powermem.env`、`pmemPath: "pmem"`,并开启 `autoCapture`、`autoRecall`、`inferOnAdd`。请确保 `pmem` 在 PATH 上(或配置 `pmemPath`),且上述 `.env` 有效
安装成功后,可用 `openclaw plugins list` 确认能看到 `memory-powermem`。若未写 `plugins.entries["memory-powermem"].config`,插件 **默认**:`mode: "cli"`、`pmemPath: "bundled"`(优先插件旁的 npm `powermem`,否则用 PATH 上的 `pmem`)、`useOpenClawModel: true`(SQLite 在 OpenClaw 状态目录 + 从 `agents.defaults.model` 注入 LLM),并开启 `autoCapture`、`autoRecall`、`inferOnAdd`。若不使用 OpenClaw 注入模型,再准备 `powermem` 的 `.env`(`envFile`)

---

## 第三步:配置 OpenClaw(可选)

若使用 **CLI 默认路径** 且 `pmem` 已在 PATH,可跳过。需要 HTTP、改 URL/API Key、或自定义 `envFile` / `pmemPath` 时再改配置。
若使用 **CLI 默认**(`bundled` + OpenClaw 模型注入),可跳过。需要 HTTP、改 URL/API Key、使用 Python 版 `pmem`(`pmemPath: "auto"` 或绝对路径)、或通过 `envFile` 时再改配置。

**CLI(默认):**

Expand All @@ -206,7 +206,7 @@ openclaw plugins install -l /path/to/memory-powermem
"config": {
"mode": "cli",
"envFile": "/home/you/.openclaw/powermem/powermem.env",
"pmemPath": "pmem",
"pmemPath": "bundled",
"autoCapture": true,
"autoRecall": true,
"inferOnAdd": true
Expand All @@ -223,15 +223,19 @@ openclaw plugins install -l /path/to/memory-powermem
"config": {
"mode": "http",
"baseUrl": "http://localhost:8000",
"httpApiVersion": "v2",
"requestConfig": { "memory_db": { "host": "db-host", "port": 2881 } },
"autoCapture": true,
"autoRecall": true,
"autoExperience": true,
"experienceRecall": true,
"inferOnAdd": true
}
```

说明:

- **CLI(默认):** 可不写 `mode` 且 `baseUrl` 为空时走 CLI;使用 `envFile` + `pmemPath`。
- **CLI(默认):** 可不写 `mode` 且 `baseUrl` 为空时走 CLI。默认 `pmemPath` 为 `bundled`(npm CLI)。需要时再配 `envFile` / `pmemPath`。
- **HTTP:** `mode` 为 `http` 时必须配置 `baseUrl`;若只写 `baseUrl` 不写 `mode`,插件会按 HTTP 处理。**不要**在 `baseUrl` 上加 `/api/v1`。若服务开了 API Key,加 `"apiKey"`。
- 改完配置后**重启 OpenClaw gateway**(或 Mac 菜单栏应用)。

Expand Down Expand Up @@ -284,16 +288,32 @@ openclaw ltm search "咖啡"

| 选项 | 必填 | 说明 |
|---------------|------|------|
| `mode` | 否 | 后端:`"cli"`(默认)或 `"http"`。不写 `mode` 但填了 `baseUrl` 时按 HTTP 处理。 |
| `baseUrl` | 是(http) | `mode` 为 `http` 时必填,PowerMem API 根地址,如 `http://localhost:8000`,不要带 `/api/v1`。 |
| `apiKey` | 否 | PowerMem 开启 API Key 鉴权时填写(http 模式)。 |
| `envFile` | 否 | CLI:PowerMem `.env`;插件默认约定 `~/.openclaw/powermem/powermem.env`。 |
| `pmemPath` | 否 | CLI 模式:`pmem` 可执行路径,默认 `pmem`。 |
| `userId` | 否 | 用于多用户隔离,默认 `openclaw-user`。 |
| `agentId` | 否 | 用于多 Agent 隔离,默认 `openclaw-agent`。 |
| `autoCapture` | 否 | 会话结束后是否自动把对话交给 PowerMem 抽取记忆,默认 `true`。 |
| `autoRecall` | 否 | 会话开始前是否自动注入相关记忆,默认 `true`。 |
| `inferOnAdd` | 否 | 写入时是否用 PowerMem 智能抽取,默认 `true`。 |
| `mode` | 否 | 后端:`"cli"`(默认)或 `"http"`。不写 `mode` 但填了 `baseUrl` 时按 HTTP 处理。 |
| `baseUrl` | 是(http) | `mode` 为 `http` 时必填,PowerMem API 根地址,如 `http://localhost:8000`,不要带 `/api/v1`。 |
| `apiKey` | 否 | PowerMem 开启 API Key 鉴权时填写(http 模式)。 |
| `httpApiVersion` | 否 | HTTP 版本:`"v1"`(默认)或 `"v2"`。 |
| `requestConfig` | 否 | HTTP v2 专用:按请求透传 `config`(如 `memory_db`)。 |
| `envFile` | 否 | CLI:PowerMem `.env`;插件默认约定 `~/.openclaw/powermem/powermem.env`。 |
| `pmemPath` | 否 | CLI:`bundled`(默认)、`auto` 或 `pmem` 的路径/命令。 |
| `userId` | 否 | 用于多用户隔离。未填或为 `"auto"` 时自动生成并保存到 `<stateDir>/powermem/identity.json`。 |
| `agentId` | 否 | 用于多 Agent 隔离。未填或为 `"auto"` 时自动生成并保存到 `<stateDir>/powermem/identity.json`。 |
| `autoCapture` | 否 | 会话结束后是否自动把对话交给 PowerMem 抽取记忆,默认 `true`。 |
| `autoRecall` | 否 | 会话开始前是否自动注入相关记忆,默认 `true`。 |
| `autoExperience` | 否 | LLM 自动提炼经验,默认 `true`。 |
| `experienceRecall` | 否 | 召回结果是否包含经验,默认 `true`。 |
| `inferOnAdd` | 否 | 写入时是否用 PowerMem 智能抽取,默认 `true`。 |
| `dualWrite` | 否 | 仅 HTTP:远端 + 本地 SQLite 双写,远端失败自动排队补传。 |
| `localDbPath` | 否 | 本地 SQLite 路径(`dualWrite`)。 |
| `localUserId` | 否 | 本地命名空间(`dualWrite`,默认 `userId`)。 |
| `localAgentId` | 否 | 本地命名空间(`dualWrite`,默认 `agentId`)。 |
| `syncOnResume` | 否 | 是否启动时补传,默认 `true`。 |
| `syncBatchSize` | 否 | 每批补传数量,默认 `50`。 |
| `syncMinIntervalMs` | 否 | 补传最小间隔,默认 `5000`。 |
| `syncBaseDelayMs` | 否 | 重试基础延迟,默认 `5000`。 |
| `syncMaxDelayMs` | 否 | 重试最大延迟,默认 `60000`。 |
| `syncMaxRetries` | 否 | 单条最大重试次数,默认 `10`。 |

**记忆划分与分享:** 建议用 `userId` / `agentId` 做逻辑隔离;HTTP v2 可用 `agent_memory_share` 在同一 `userId` 下做跨 Agent 共享。若需跨 `userId` + `agentId`,可用 `cross_scope_share` 按 `query` 检索源记忆并复制到目标命名空间。

**自动抓取**:会话结束时,会把本轮用户/助手文本发给 PowerMem(`infer: true`),由 PowerMem 抽取并落库。每轮最多 3 条,每条约 6000 字符以内。

Expand All @@ -306,6 +326,13 @@ openclaw ltm search "咖啡"
- **memory_recall** — 按查询搜索长期记忆
- **memory_store** — 写入一条记忆(可选是否智能抽取)
- **memory_forget** — 按记忆 ID 或按搜索条件删除
- **experience_store** — 写入经验
- **experience_recall** — 查询经验
- **agent_memory_add** — 给其它 Agent 增加记忆(HTTP v2)
- **agent_memory_list** — 列出 Agent 记忆(HTTP v2)
- **agent_memory_share** — 共享 Agent 记忆(HTTP v2)
- **agent_memory_shared** — 列出共享记忆(HTTP v2)
- **cross_scope_share** — 跨 `userId` / `agentId` 复制共享记忆(HTTP v2)。参数:`fromUserId`、`fromAgentId`、`toUserId`、`toAgentId`、`query`,可选 `limit`、`scoreThreshold`、`inferOnTarget`。

---

Expand All @@ -321,7 +348,7 @@ openclaw ltm search "咖啡"

**1. `openclaw ltm health` 报错连不上**

- **CLI:** `pmem` 在 PATH 或 `pmemPath` 正确;`envFile` 指向有效 `.env`。
- **CLI:** 插件已安装 npm `powermem`(`bundled`),或 `pmemPath` 正确;未用 OpenClaw 注入时再保证 `envFile`。
- **HTTP:** PowerMem 已启动(方式 A 终端或 Docker);`baseUrl` 正确(本机常用 `http://localhost:8000`,注意与 `127.0.0.1` 一致性问题)。
- 若 OpenClaw 和 PowerMem 不在同一台机器,把 `localhost` 改成 PowerMem 所在机器的 IP 或域名。

Expand Down
Loading
Loading