Metadata-Version: 2.4
Name: hermes-hy-memory
Version: 0.1.2
Summary: HY Memory provider plugin for Hermes Agent (native, 100% passive injection)
Author: alvinfei
License: MIT
Keywords: hermes,memory,llm,agent,plugin
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: hy-memory>=1.2.17
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"

# HY Memory Provider for Hermes

Hermes Agent 的原生 Memory Provider 插件 —— **第一梯队 100% 被动注入**。

## 工作原理

Hermes 框架在每次 LLM 调用前自动触发 `prefetch(query)`，本 Provider：
1. 用 query 在 HY Memory 里搜（chat 链路三路召回）
2. 把命中结果按 layer 格式化（`§ [profile]` / `§ [intent]` / `§`）
3. Hermes 把这块文本注入 system prompt

**用户无需任何额外操作**，记忆自动工作。

每轮对话结束 Hermes 调 `sync_turn(user, assistant)`，Provider 提交到内部线程池异步写入，不阻塞主流程。

## 安装

> SDK 包 `hy-memory` 已发布到**公网 PyPI**（pypi.org），直接 `pip install` 即可，无需任何额外源或凭证。

> **chroma 后端需 `sqlite3 >= 3.35`**（默认 `MEMORY_VECTOR_STORE=chroma`）。系统 sqlite 过低
> （旧版 CentOS/Linux 会报 `unsupported version of sqlite3`）时：`pip install pysqlite3-binary`
> 并在进程入口 swap（`import sys; sys.modules["sqlite3"]=__import__("pysqlite3")`），
> 或改用 `MEMORY_VECTOR_STORE=qdrant` / `faiss`。

### 方式 A：通过 `hermes memory setup`（推荐）

```bash
hermes memory setup hy-memory
```

Hermes 会按 `plugin.yaml` 的 `pip_dependencies` 自动安装 `hy-memory`，并启动配置向导询问 `HY_MEMORY_USER_ID` / `HY_MEMORY_AGENT_ID` / mode。

### 方式 B：手动 pip install

```bash
# 装这个 plugin（自动拉 hy-memory 作为依赖）
pip install hermes-hy-memory

# 让 Hermes 启用
hermes config set memory.provider hy-memory
```

### 方式 C：folder-drop（开发调试）

```bash
cp -r plugins/native/hermes ~/.hermes/plugins/memory/hy-memory
pip install "hy-memory>=1.2.17"
```

### 内网安装（腾讯内部，可选）

腾讯内网用内部包 `hy-memory-internal`（与公网 `hy-memory` 同源，import 同为 `hy_memory`），
通过腾讯镜像源安装，无需凭证：

```bash
pip install "hy-memory-internal>=0.1.5.14" --index-url https://mirrors.tencent.com/pypi/simple/
```

## 配置

### 环境变量

| 变量 | 必填 | 默认 | 说明 |
|---|---|---|---|
| `HY_MEMORY_USER_ID` | ✅ | — | 一级隔离 key（你的记忆命名空间） |
| `HY_MEMORY_AGENT_ID` | ❌ | `hermes` | 二级隔离 key |
| `HY_MEMORY_MODE` | ❌ | `pro` | 处理模式：`lite` / `pro` / `ultra` |
| `HY_MEMORY_PREFETCH_MAX_CHARS` | ❌ | `2000` | prefetch 注入文本总字符数上限 |
| `HY_MEMORY_SYNC_WORKERS` | ❌ | `2` | sync_turn 后台线程池大小 |
| `HY_MEMORY_SHUTDOWN_GRACE_SEC` | ❌ | `10` | shutdown 等 in-flight 写入的最长秒数 |
| `OPENAI_API_KEY`（或对应 LLM/embedder key） | ✅* | — | `pro`/`ultra` 必须；`lite` 仅 embed 用得到 |

*HY Memory SDK 自身的 LLM/Embedder 配置（详见 `hy-memory-internal` 文档）。

### `~/.hermes/config.yaml`

```yaml
memory:
  provider: hy-memory
```

环境变量优先级最高，可在 `~/.hermes/.env` 里持久化（`hermes memory setup` 自动写）。

## 处理模式（`HY_MEMORY_MODE`）

| 模式 | 写入流程 | 速度 | 召回质量 |
|---|---|---|---|
| `lite` | 纯 embedding 写入（不调 LLM） | 最快 | 仅向量相似 |
| `pro`（默认） | LLM 抽取事实/身份 + reconcile 演化 | 中 | 含画像 + 事实层 |
| `ultra` | pro + System2 异步认知（Schema/Intention） | 最完整 | + 跨域归纳 + 前瞻意图 |

> ⚠️ **`lite` 模式不适用于 Hermes 被动注入 / 检索。** lite 只做 embedding、不经 LLM 抽取，
> 记忆停留在 `L1_RAW` 层；而 SDK 的 `list` / `search` 会过滤掉 `L1_RAW`，因此 lite 写入的记忆
> **无法被 `prefetch` 召回**（表现为写入成功但检索恒为空）。Hermes 集成请使用 `pro`（默认）或
> `ultra`；`lite` 仅适合“只写、不依赖语义召回”的特殊场景。

## CLI

`pip install` 后可用 `hermes-hy-memory` 子命令做体检和手动操作（脱离 Hermes 主进程）：

```bash
# 体检：env 齐 / Client 能否构造 / list 能否跑通（只读）
hermes-hy-memory doctor

# 手动写入
hermes-hy-memory add "我喜欢 K-Pop 但更喜欢 Jazz"

# 手动搜索
hermes-hy-memory search "音乐口味" --limit 5

# 列出最近 20 条
hermes-hy-memory list

# 跨用户测试（覆盖 env）
hermes-hy-memory search "x" --user-id other_user --agent-id test
```

被 Hermes 主 CLI 加载后也可：

```bash
hermes hy-memory doctor
```

## Hooks

| Hook | 触发时机 | 行为 |
|---|---|---|
| `prefetch(query)` | 每次 LLM 调用前 | 搜记忆 → 注入 system prompt |
| `sync_turn(user, ast)` | 每轮对话结束 | 提交线程池异步写入 |
| `on_session_end(msgs)` | 会话结束 | 等 in-flight 完成 + 尾部补提取 |
| `on_pre_compress(msgs)` | 上下文压缩前 | 同 `on_session_end`，保住即将被裁的内容 |
| `on_memory_write(action, target, content)` | Hermes 内置 memory 命令 | `add` 同步到 HY Memory；`delete` 跳过（target ID 不互通） |

## Tools（LLM 主动调用，可选）

| Tool | 用途 |
|---|---|
| `memory_search(query, limit)` | 搜索记忆 |
| `memory_add(content)` | 写入一条记忆 |
| `memory_delete(memory_id)` | 删除一条记忆 |
| `memory_list(limit)` | 列出当前 user/agent 的记忆 |

即使关掉 tools，prefetch 的被动注入也保证每次 LLM 调用都能看到相关记忆。

## 故障排查

### `provider not initialized` 或所有 hook 静默 no-op

跑一遍体检：
```bash
hermes-hy-memory doctor
```

常见原因：
1. `HY_MEMORY_USER_ID` 没设
2. embed/LLM key 没设（`OPENAI_API_KEY` 等）→ `HyMemoryClient(mode="pro")` 构造失败
3. SDK 没装：`pip install hy-memory`（内网：`pip install hy-memory-internal --index-url https://mirrors.tencent.com/pypi/simple/`）

### prefetch 没注入任何记忆

- 库里**真没相关记忆** —— 用 `hermes-hy-memory list` 确认
- query 太短（< 3 字符）或在跳过列表里（`ok`/`好的`/`thanks` 等）—— 设计如此
- 中文 query 命中率低？SDK ≥ 0.1.5.11.dev2 已修过 BM25 中文分词不对称的 bug，确认版本

### sync_turn 似乎没写入

- 默认 daemon 线程，主进程退出会被 kill。生产部署用 `hermes` daemon 模式
- 提高 `HY_MEMORY_SHUTDOWN_GRACE_SEC` 让 shutdown 多等几秒
- 检查日志 `[hermes] sync_turn failed: ...`

### `cross-loop` 错误（多 client 场景）

如果你的 Hermes 部署同时跑了多个 `HyMemoryClient` 实例（比如多租户 server），需要 SDK ≥ 0.1.5.11.dev2 + 用 `SharedRuntime`：

```python
from hy_memory import HyMemoryClient, SharedRuntime
runtime = await SharedRuntime.create(base_config)
client = HyMemoryClient(cfg, runtime=runtime)
```

本 plugin 单 Hermes 进程默认走 solo mode 的 client，不需要这个。

## 与 Mem0 风格的对比

[Mem0 的 Hermes 集成](https://github.com/mem0ai/mem0)依赖 **TypeScript SDK**，本插件用 **Python SDK**。HY Memory 提供 lite/pro/ultra 三档处理深度（lite 不调 LLM，pro 标准抽取，ultra 加 System2 认知）；Mem0 是单档 LLM 抽取。

## 开发

```bash
cd plugins/native/hermes
python -m pytest tests/ -v
```

测试 mock 掉 `HyMemoryClient`，无外部依赖（不需要 OPENAI_API_KEY、不需要起 Qdrant）。

## 版本

| Plugin | SDK 依赖 | 备注 |
|---|---|---|
| 0.1.2 | `hy-memory>=1.2.17`（内网 `hy-memory-internal>=0.1.5.14`） | 发布到公网 PyPI（`hermes-hy-memory`）；channel-dict flatten 修复 |
| 0.1.0 | `hy-memory-internal>=0.1.5.11.dev2` | 含 SharedRuntime / BM25 中文修复 / Chroma keyword_search / stdout 日志 |
