@evermind-ai/openclaw-plugin 1.1.0
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/README.md +400 -0
- package/README.zh.md +400 -0
- package/index.js +397 -0
- package/openclaw.plugin.json +50 -0
- package/package.json +40 -0
- package/src/assembler.js +96 -0
- package/src/compaction.js +85 -0
- package/src/config.js +14 -0
- package/src/context-engine.js +283 -0
- package/src/formatter.js +152 -0
- package/src/http-client.js +46 -0
- package/src/lifecycle.js +65 -0
- package/src/memory-api.js +77 -0
- package/src/message-utils.js +163 -0
- package/src/subagent.js +116 -0
- package/src/types.js +107 -0
package/README.zh.md
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# EverMemOS ContextEngine OpenClaw 插件
|
|
2
|
+
|
|
3
|
+
通过 [EverMemOS](https://github.com/EverMind-AI/EverMemOS) 为 **OpenClaw 3.8+** 提供全生命周期记忆管理。
|
|
4
|
+
|
|
5
|
+
> **专为 OpenClaw 3.8+ ContextEngine API 构建** - 利用最新的 ContextEngine 生命周期钩子实现智能记忆管理。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 功能特性
|
|
10
|
+
|
|
11
|
+
- **Bootstrap**: 插件加载时后端健康检查
|
|
12
|
+
- **Assemble**: 每次 agent 轮次前的查询感知上下文检索
|
|
13
|
+
- **AfterTurn**: 每轮结束后及时提取记忆(而非仅会话结束时)
|
|
14
|
+
- **Compact**: 参与会话压缩以优化上下文窗口
|
|
15
|
+
- **边界检测**: 通过 EverMemOS 的边界检测算法智能提取记忆
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 快速开始
|
|
20
|
+
|
|
21
|
+
### 前置要求
|
|
22
|
+
|
|
23
|
+
| 要求 | 版本 | 说明 |
|
|
24
|
+
|-------------|---------|-------|
|
|
25
|
+
| **Node.js** | 18+ | 运行插件 |
|
|
26
|
+
| **Python** | 3.10+ | 运行 EverMemOS 后端 |
|
|
27
|
+
| **Docker** | 20.10+ | 基础设施服务 |
|
|
28
|
+
| **OpenClaw** | 3.8+ | 支持 ContextEngine |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 步骤 1: 安装 EverMemOS 后端
|
|
33
|
+
|
|
34
|
+
### 克隆并设置
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 克隆 EverMemOS 仓库
|
|
38
|
+
git clone https://github.com/EverMind-AI/EverMemOS.git
|
|
39
|
+
cd EverMemOS
|
|
40
|
+
|
|
41
|
+
# 启动 Docker 服务(MongoDB、Elasticsearch、Milvus、Redis)
|
|
42
|
+
docker compose up -d
|
|
43
|
+
|
|
44
|
+
# 安装 uv 包管理器
|
|
45
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
46
|
+
|
|
47
|
+
# 安装 Python 依赖
|
|
48
|
+
uv sync
|
|
49
|
+
|
|
50
|
+
# 配置 API 密钥
|
|
51
|
+
cp env.template .env
|
|
52
|
+
# 编辑 .env 并设置你的 LLM_API_KEY 和 VECTORIZE_API_KEY
|
|
53
|
+
|
|
54
|
+
# 启动后端服务(默认: http://localhost:1995)
|
|
55
|
+
uv run python src/run.py
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 验证后端
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
curl http://localhost:1995/health
|
|
62
|
+
# 预期响应: {"status": "healthy", ...}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
> **详细 EverMemOS 安装指南**,请参阅 [官方安装文档](https://github.com/EverMind-AI/EverMemOS/blob/main/docs/installation/SETUP.md)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 步骤 2: 安装插件
|
|
70
|
+
|
|
71
|
+
### 选项 A: 本地开发(推荐)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# 克隆此仓库
|
|
75
|
+
git clone https://github.com/EverMind-AI/evermemos-openclaw-plugin.git
|
|
76
|
+
cd evermemos-openclaw-plugin
|
|
77
|
+
|
|
78
|
+
# 安装依赖
|
|
79
|
+
npm install
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 选项 B: 通过 npm
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install @evermind-ai/openclaw-plugin
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 步骤 3: 配置 OpenClaw
|
|
91
|
+
|
|
92
|
+
编辑 `~/.openclaw/openclaw.json`:
|
|
93
|
+
|
|
94
|
+
### 3.1 添加插件路径
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"plugins": {
|
|
99
|
+
"load": {
|
|
100
|
+
"paths": [
|
|
101
|
+
"/path/to/openclaw/extensions/feishu",
|
|
102
|
+
"/path/to/openclaw/extensions/memory-openviking",
|
|
103
|
+
"/Users/admin/EverMind/evermemos-openclaw-plugin" // 添加此行
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3.2 启用插件
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"plugins": {
|
|
115
|
+
"allow": [
|
|
116
|
+
"memory-openviking",
|
|
117
|
+
"feishu",
|
|
118
|
+
"mem9",
|
|
119
|
+
"evermemos-openclaw-plugin" // 添加此行
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 3.3 设置 ContextEngine 插槽(OpenClaw 3.8+)
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"plugins": {
|
|
130
|
+
"slots": {
|
|
131
|
+
"memory": "none",
|
|
132
|
+
"contextEngine": "evermemos-openclaw-plugin" // 使用 EverMemOS ContextEngine
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 3.4 添加插件配置
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"plugins": {
|
|
143
|
+
"entries": {
|
|
144
|
+
"evermemos-openclaw-plugin": {
|
|
145
|
+
"enabled": true,
|
|
146
|
+
"config": {
|
|
147
|
+
"baseUrl": "http://localhost:1995",
|
|
148
|
+
"userId": "evermemos-user",
|
|
149
|
+
"groupId": "evermemos-group",
|
|
150
|
+
"topK": 5,
|
|
151
|
+
"memoryTypes": ["episodic_memory", "profile", "agent_skill", "agent_case"],
|
|
152
|
+
"retrieveMethod": "hybrid"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 步骤 4: 重启 OpenClaw
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
openclaw gateway restart
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 步骤 5: 验证安装
|
|
171
|
+
|
|
172
|
+
检查 OpenClaw 日志中的插件加载信息:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
[evermemos] Registering EverMemOS ContextEngine plugin
|
|
176
|
+
[evermemos] bootstrap: session=xxx, key=xxx
|
|
177
|
+
[evermemos] bootstrap: backend healthy, status=ok
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 测试
|
|
183
|
+
|
|
184
|
+
### 测试记忆存储
|
|
185
|
+
|
|
186
|
+
向 agent 发送消息:
|
|
187
|
+
```
|
|
188
|
+
记住:我最喜欢的颜色是蓝色
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 测试记忆检索
|
|
192
|
+
|
|
193
|
+
稍后询问:
|
|
194
|
+
```
|
|
195
|
+
我最喜欢什么颜色?
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Agent 应该能够从 EverMemOS 中回忆起该信息。
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 配置说明
|
|
203
|
+
|
|
204
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
205
|
+
|-----------|------|---------|-------------|
|
|
206
|
+
| `baseUrl` | string | `http://localhost:1995` | EverMemOS 服务地址 |
|
|
207
|
+
| `userId` | string | `evermemos-user` | 用户身份,用于记忆归属 |
|
|
208
|
+
| `groupId` | string | `evermemos-group` | 组 ID,用于共享记忆 |
|
|
209
|
+
| `topK` | integer | `5` | 最多检索的记忆条目数 |
|
|
210
|
+
| `memoryTypes` | string[] | 见下方 | 搜索的记忆类型 |
|
|
211
|
+
| `retrieveMethod` | string | `hybrid` | 检索策略 |
|
|
212
|
+
|
|
213
|
+
### 记忆类型
|
|
214
|
+
|
|
215
|
+
| 值 | 说明 |
|
|
216
|
+
|-------|-------------|
|
|
217
|
+
| `episodic_memory` | 过往对话片段 |
|
|
218
|
+
| `profile` | 用户档案和偏好 |
|
|
219
|
+
| `agent_case` | 相似历史案例 |
|
|
220
|
+
| `agent_skill` | Agent 技能知识 |
|
|
221
|
+
|
|
222
|
+
### 检索策略
|
|
223
|
+
|
|
224
|
+
| 值 | 说明 |
|
|
225
|
+
|-------|-------------|
|
|
226
|
+
| `keyword` | 全文关键词搜索 |
|
|
227
|
+
| `vector` | 语义向量搜索 |
|
|
228
|
+
| `hybrid` | 关键词 + 向量融合 |
|
|
229
|
+
| `rrf` | 倒序排名融合 |
|
|
230
|
+
| `agentic` | Agent 驱动的自适应检索 |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 架构
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
238
|
+
│ OpenClaw 核心 │
|
|
239
|
+
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
|
|
240
|
+
│ │ 消息流 │ │ 会话管理 │ │ Token 预算管理 │ │
|
|
241
|
+
│ │ │ │ │ │ (压缩) │ │
|
|
242
|
+
│ └──────┬──────┘ └──────┬───────┘ └──────────┬──────────────┘ │
|
|
243
|
+
└─────────┼────────────────┼─────────────────────┼────────────────┘
|
|
244
|
+
│ │ │
|
|
245
|
+
▼ ▼ ▼
|
|
246
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
247
|
+
│ EverMemOS ContextEngine │
|
|
248
|
+
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────────────┐ │
|
|
249
|
+
│ │bootstrap│ │ ingest │ │afterTurn │ │ assemble │ │
|
|
250
|
+
│ └────┬────┘ └────┬────┘ └────┬─────┘ └────────┬─────────┘ │
|
|
251
|
+
└───────┼─────────────┼─────────────┼─────────────────┼─────────────┘
|
|
252
|
+
│ │ │ │
|
|
253
|
+
▼ ▼ ▼ ▼
|
|
254
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
255
|
+
│ EverMemOS 后端 │
|
|
256
|
+
│ http://localhost:1995 │
|
|
257
|
+
│ │
|
|
258
|
+
│ • 边界检测 • 记忆提取 • 向量搜索 • 档案构建 │
|
|
259
|
+
│ • 聚类 • 预测 │
|
|
260
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## OpenClaw 3.8+ ContextEngine API
|
|
266
|
+
|
|
267
|
+
本插件利用 OpenClaw 3.8 的 **ContextEngine API** 实现精细的生命周期控制:
|
|
268
|
+
|
|
269
|
+
| 生命周期钩子 | 调用时机 | 插件行为 |
|
|
270
|
+
|----------------|-------------|------------------|
|
|
271
|
+
| `bootstrap()` | 会话开始 | 健康检查,初始化状态 |
|
|
272
|
+
| `assemble()` | 每次 agent 轮次前 | 检索相关记忆,注入上下文 |
|
|
273
|
+
| `afterTurn()` | 每次 agent 轮次后 | 保存新消息到 EverMemOS |
|
|
274
|
+
| `compact()` | 超出 token 预算时 | 评估压缩需求 |
|
|
275
|
+
| `dispose()` | 会话结束时 | 清理会话状态 |
|
|
276
|
+
|
|
277
|
+
### 与传统记忆插件的差异
|
|
278
|
+
|
|
279
|
+
| 传统记忆钩子 | ContextEngine API |
|
|
280
|
+
|--------------------|-------------------|
|
|
281
|
+
| 简单存储/检索 | 全生命周期管理 |
|
|
282
|
+
| 自动时机 | 可控时机 |
|
|
283
|
+
| 有限的上下文控制 | 查询感知组装 |
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 生命周期流程
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
┌──────────────┐
|
|
291
|
+
│ bootstrap() │ → 健康检查,初始化会话状态
|
|
292
|
+
└──────┬───────┘
|
|
293
|
+
│
|
|
294
|
+
▼
|
|
295
|
+
┌──────────────┐ ┌──────────────────┐
|
|
296
|
+
│ assemble() │ ── │ 记忆搜索 │ → 注入上下文作为系统消息
|
|
297
|
+
│ (每轮) │ │ GET /memories/ │
|
|
298
|
+
└──────┬───────┘ │ search │
|
|
299
|
+
│ └──────────────────┘
|
|
300
|
+
▼
|
|
301
|
+
┌──────────────────┐
|
|
302
|
+
│ [Agent 轮次] │
|
|
303
|
+
└──────┬───────────┘
|
|
304
|
+
│
|
|
305
|
+
▼
|
|
306
|
+
┌──────────────┐ ┌──────────────────┐
|
|
307
|
+
│ afterTurn() │ ── │ 保存记忆 │ → POST /memories
|
|
308
|
+
│ (每轮) │ │ 边界检测 │
|
|
309
|
+
└──────┬───────┘ └──────────────────┘
|
|
310
|
+
│
|
|
311
|
+
▼
|
|
312
|
+
┌──────────────┐
|
|
313
|
+
│ compact() │ → 评估是否需要压缩
|
|
314
|
+
└──────────────┘
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## 故障排查
|
|
320
|
+
|
|
321
|
+
### 插件未加载
|
|
322
|
+
|
|
323
|
+
**症状**: 插件未出现在 OpenClaw 日志中
|
|
324
|
+
|
|
325
|
+
**解决方案**:
|
|
326
|
+
1. 检查 `plugins.allow` 是否包含 `"evermemos-openclaw-plugin"`
|
|
327
|
+
2. 确认 `plugins.load.paths` 包含正确的插件目录
|
|
328
|
+
3. 检查 `plugins.entries.evermemos-openclaw-plugin.enabled` 是否为 `true`
|
|
329
|
+
|
|
330
|
+
### 后端连接失败
|
|
331
|
+
|
|
332
|
+
**症状**: `bootstrap: backend unhealthy` 或超时错误
|
|
333
|
+
|
|
334
|
+
**解决方案**:
|
|
335
|
+
1. 验证 EverMemOS 后端是否运行: `curl http://localhost:1995/health`
|
|
336
|
+
2. 检查 `baseUrl` 配置是否与后端 URL 匹配
|
|
337
|
+
3. 检查防火墙/网络设置
|
|
338
|
+
|
|
339
|
+
### 记忆未被保存
|
|
340
|
+
|
|
341
|
+
**症状**: 后端日志中没有记忆提取记录
|
|
342
|
+
|
|
343
|
+
**解决方案**:
|
|
344
|
+
1. 验证 `plugins.slots.contextEngine` 设置为 `"evermemos-openclaw-plugin"`
|
|
345
|
+
2. 发送更多消息 - EverMemOS 使用边界检测,需要足够的上下文
|
|
346
|
+
3. 检查后端日志中的 `[Boundary Detection]` 消息
|
|
347
|
+
|
|
348
|
+
### 记忆未被检索
|
|
349
|
+
|
|
350
|
+
**症状**: Agent 无法回忆之前的信息
|
|
351
|
+
|
|
352
|
+
**解决方案**:
|
|
353
|
+
1. 验证记忆已被提取(检查后端日志中的 "Successfully extracted MemCell")
|
|
354
|
+
2. 检查查询长度是否 ≥ 3 个字符
|
|
355
|
+
3. 增大 `topK` 值以检索更多记忆
|
|
356
|
+
4. 尝试不同的 `retrieveMethod`(如 `hybrid` 或 `agentic`)
|
|
357
|
+
|
|
358
|
+
### 向量服务错误
|
|
359
|
+
|
|
360
|
+
**症状**: `VllmVectorizeService API error: 502`
|
|
361
|
+
|
|
362
|
+
**解决方案**: 这是正常现象 - EverMemOS 会自动回退到备用嵌入服务。记忆提取继续正常工作。
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## 项目结构
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
├── index.js # ContextEngine 工厂及主入口
|
|
370
|
+
├── package.json
|
|
371
|
+
├── openclaw.plugin.json # 插件元数据 (kind: context-engine)
|
|
372
|
+
├── README.md # 英文文档
|
|
373
|
+
├── README.zh.md # 中文文档
|
|
374
|
+
└── src/
|
|
375
|
+
├── config.js # 配置解析
|
|
376
|
+
├── memory-api.js # EverMemOS REST API 客户端
|
|
377
|
+
├── formatter.js # 记忆响应解析与格式化
|
|
378
|
+
├── message-utils.js # 消息收集与格式转换
|
|
379
|
+
├── http-client.js # HTTP 客户端(超时与重试)
|
|
380
|
+
├── types.js # JSDoc 类型定义
|
|
381
|
+
├── assembler.js # 查询感知上下文组装
|
|
382
|
+
├── lifecycle.js # 轮次级提取钩子
|
|
383
|
+
├── compaction.js # 压缩评估逻辑
|
|
384
|
+
├── subagent.js # 子代理生命周期跟踪
|
|
385
|
+
└── context-engine.js # 核心 ContextEngine 实现
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## 相关链接
|
|
391
|
+
|
|
392
|
+
- [EverMemOS](https://github.com/EverMind-AI/EverMemOS) - 后端记忆系统
|
|
393
|
+
- [OpenClaw](https://github.com/openclaw-org/openclaw) - Agent 框架
|
|
394
|
+
- [English Documentation](README.md) - 英文文档
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 许可证
|
|
399
|
+
|
|
400
|
+
Apache-2.0
|