# QQ 桥接 + 消息闭环实施计划

> **Status:** Ready for implementation

## Context

Butler-Shell 核心功能已完成（tmux 会话、Agent 自然语言理解、Mock 测试），但 QQ 对话链路未打通：

1. **NapCatQQ 未安装**：服务器是 OpenCloudOS 9.4，没有 Docker，也没有 xvfb/QQ
2. **消息回复链路断裂**：Gateway 只接收消息，处理完后没有把回复发回 QQ
3. **Gateway 直接处理消息**：当前 Gateway 把消息发给 Inngest，但 Inngest 链路复杂且 mock 端点已绕过它，应该让 Gateway 直接调用消息处理逻辑

## 实施步骤

### Step 1: 安装 NapCatQQ

在 OpenCloudOS 9.4 上安装 NapCat + xvfb + QQ。仅 SSH 环境，用 TUI 方式配置和登录。

```bash
# 1. 安装 xvfb（headless 运行 QQ 必须）
yum install -y xorg-x11-server-Xvfb xorg-x11-xauth

# 2. 用 NapCat Installer 安装（带 TUI-CLI）
curl -o napcat.sh https://nclatest.znin.net/NapNeko/NapCat-Installer/main/script/install.sh
bash napcat.sh --docker n --cli y

# 3. 启动 QQ（xvfb 虚拟帧缓冲）
xvfb-run -a qq --no-sandbox -q <QQ号>

# 4. 首次登录 - 终端会显示二维码，用手机 QQ 扫码
#    或使用 TUI-CLI: sudo napcat

# 5. 配置 WebSocket Server（通过 TUI-CLI 或直接编辑配置文件）
#    配置文件: /opt/QQ/resources/app/app_launcher/napcat/config/onebot11_<QQ号>.json
#    设置 websocketServers: host=0.0.0.0, port=3001
```

首次登录需要手机 QQ 扫码（终端显示二维码或 TUI-CLI 中扫码）。

**修改文件:** 无代码修改，纯环境配置

### Step 2: 修复消息回复链路

**问题:** `NapCatGateway.send_private_message()` 存在，但消息处理完成后从未调用它。

**方案:** 在 `main.py` 中，Gateway 收到消息后直接调用 `/api/mock/message` 的处理逻辑，拿到 `reply` 后通过 `gateway.send_private_message()` 发回 QQ。

**修改文件:**
- `src/butler/main.py` - 重构 `handle_message` 回调，处理完直接回复

核心改动：

```python
# main.py - run_gateway 中
async def handle_message(event):
    # 调用消息处理逻辑
    result = await _process_message(str(event.user_id), event.message)
    # 把回复发回 QQ
    reply = result.get("reply", "")
    if reply:
        await gateway.send_private_message(event.user_id, reply)
```

需要把 `/api/mock/message` 的处理逻辑提取为共享函数 `_process_message()`。

### Step 3: Gateway 连接容错优化

**问题:** NapCat 未启动时 Gateway 每 30 秒报错，但不影响 API。

**方案:** 已在之前修复（30 秒重试 + 提示），无需额外改动。

**修改文件:** 无

---

## 关键文件

| 文件 | 改动 |
|------|------|
| `src/butler/main.py` | 提取 `_process_message()`，Gateway 回调调用并回复 QQ |
| `src/butler/gateway/napcat.py` | 无改动（已有 send_private_message） |

## 验证步骤

```bash
# 1. 安装 NapCat 后启动
xvfb-run -a qq --no-sandbox -q <QQ号>

# 2. 重启 Butler-Shell
python -m butler.main

# 3. 用另一个 QQ 号给 Bot 发消息："当前目录有什么文件"
#    期望：Bot 回复自然语言总结

# 4. Mock 测试仍然可用
python scripts/mock_test.py 当前目录有多少个文件
```
