# OpenClaw Bridge — QQ AI Reply Plugin > 将 QQ 消息转发到 OpenClaw Gateway,由 AI agent 自动处理并回复。 > 本 README 面向 AI agent(OpenClaw 基础智能体),引导其完成全流程部署(NapCat → qqrebot → 插件 → agent)。 ## 架构 ``` QQ 用户 →→→ NapCat(Docker) │ │ HTTP POST(事件推送:6097→qqrebot:25580) ▼ qqrebot(HTTP Server :25580) ← 消息接收 │ ├── 执行 openclaw_bridge 插件 │ │ │ │ HTTP POST /v1/chat/completions │ ▼ │ OpenClaw Gateway(:18789) │ │ │ ▼ │ qq-agent(AI 模型) │ │ ◄── 返回回复文本 ──┘ │ │ HTTP POST(send_private_msg / send_group_msg) ▼ NapCat(Docker:6097)→ 回复发送到 QQ ``` **关键通信链路(全是 HTTP,无 WebSocket):** | 链路 | 方向 | 协议 | 地址 | |---|---|---|---| | NapCat → qqrebot | 事件推送 | HTTP POST | `http://172.17.0.1:25580/` | | 插件 → OpenClaw | AI 请求 | HTTP POST | `127.0.0.1:18789` | | 插件 → NapCat | 发送回复 | HTTP POST | `127.0.0.1:6097` | | 脚本 → NapCat | 发消息/管理 | HTTP POST | `127.0.0.1:6097` | ## 前提条件 | 组件 | 状态 | 由本仓库部署 | |---|---|---| | OpenClaw Gateway | 假设已运行 | ❌(由用户自行部署) | | NapCat(Docker) | 需部署 | ✅ | | qqrebot(消息接收器)| 需部署 | ✅ | | openclaw_bridge 插件 | 需部署 | ✅ | | qq-agent(AI agent) | 需创建 | ✅ | | QQ 技能/脚本 | 需部署 | ✅ | ## 部署步骤(阅读此文档的 AI agent 请按以下顺序执行) > ⚠️ **关于变量持久化:** 以下每个步骤中的 bash 代码块可能在独立 shell 中执行。 > agent 应**将变量保存到文件**以便跨步骤使用,而不是依赖 `export` 在当前 shell 的生存期。 > 建议策略:Step 1 执行后,将导出的变量写入 `/tmp/env_vars.sh`, > 后续每个 bash 块开头先 `source /tmp/env_vars.sh` 恢复环境。 --- ### 第1步:环境自动检测 + 询问关键信息 本步骤将自动推导绝大多数配置,**只需向用户确认两个不可推导的值**。 #### 1.0 前置依赖检查 agent 执行以下检查,缺少即自动安装: ```bash # ⚠️ 本机如果缺少 apt-get(如 Alpine),请自行替换为 apk # 本教程以 Debian/Ubuntu 系为例 MISSING="" for cmd in git wget docker python3 curl tar; do command -v $cmd &>/dev/null || MISSING="$MISSING $cmd" done if [ -n "$MISSING" ]; then echo "❌ 缺少命令:$MISSING" echo "请安装后重试:apt-get install -y$MISSING" exit 1 fi # Docker daemon 检查 if ! docker info &>/dev/null; then echo "❌ Docker 未运行或权限不足" echo " 请确保 Docker 已安装且当前用户有 docker 组权限" exit 1 fi # python3-venv if ! python3 -m venv --help &>/dev/null; then apt-get update && apt-get install -y python3-venv fi echo "✅ 所有前置依赖已就绪" ``` #### 1.1 设置默认值 + 持久化到文件 ```bash # ─── 可自动推导的变量,全部使用默认值 ─── # Agent 唯一标识(默认 qq-agent,用户可改但通常不需要) NEW_AGENT_ID="${NEW_AGENT_ID:-qq-agent}" AGENT_WORKSPACE="/home/program/${NEW_AGENT_ID}-workspace" # 共享目录路径 SHARED_DIR="${SHARED_DIR:-/opt/napcat_shared}" # NapCat HTTP API 地址(同机部署走 127.0.0.1) NAPCAT_HOST="127.0.0.1" # OneBot HTTP API 端口(与 WebUI 端口 6099 不同) NAPCAT_API_PORT="${NAPCAT_API_PORT:-6097}" # 从 NapCat Docker 容器角度看到的 qqrebot 地址 # 同机部署时 NapCat 通过 Docker 网关访问宿主机 QQREBOT_HOST="172.17.0.1:25580" # Gateway Token:自动从本机 OpenClaw 配置文件读取 GATEWAY_TOKEN=$(python3 -c " import json with open('$HOME/.openclaw/openclaw.json') as f: cfg = json.load(f) print(cfg.get('gateway', {}).get('auth', {}).get('token', '')) " 2>/dev/null) # ─── 持久化到文件,供后续步骤使用 ─── cat > /tmp/env_vars.sh << EOF NEW_AGENT_ID='${NEW_AGENT_ID}' AGENT_WORKSPACE='${AGENT_WORKSPACE}' SHARED_DIR='${SHARED_DIR}' NAPCAT_HOST='${NAPCAT_HOST}' NAPCAT_API_PORT='${NAPCAT_API_PORT}' QQREBOT_HOST='${QQREBOT_HOST}' GATEWAY_TOKEN='${GATEWAY_TOKEN}' EOF echo "变量已写入 /tmp/env_vars.sh,后续步骤请先 source 该文件" ``` > 持久化文件使用 **无引号 heredoc**(`<< EOF`),bash 在 Step 1.1 执行时即展开 `${}` 变量。 > 后续步骤每次执行 bash 代码块前,先 `source /tmp/env_vars.sh` 恢复环境。 #### 1.2 向用户确认 只有以下两项无法自动推导,agent 需向用户询问: | 变量 | 必须 | 说明 | |---|---|---| | `ADMIN_QQ` | ✅ | 管理员 QQ 号,用于白名单和安全告警上报 | | `GATEWAY_TOKEN` | 看情况 | 自动读取失败时(空值)才需要用户提供 | > 其余变量(`NEW_AGENT_ID`、`SHARED_DIR`、`NAPCAT_HOST`、`NAPCAT_API_PORT`、`QQREBOT_HOST`)全部使用默认值即可。仅在跨机部署时需要用户调整 `NAPCAT_HOST` 或 `NAPCAT_API_PORT`。 #### 1.3 获取必填值并持久化 ```bash # 用户已提供 ADMIN_QQ(由 agent 通过询问获得) # 将该值追加到持久化变量文件 source /tmp/env_vars.sh if [ -z "$ADMIN_QQ" ]; then echo "❌ ADMIN_QQ 为空,请提供" exit 1 fi if [ -z "$GATEWAY_TOKEN" ]; then echo "❌ GATEWAY_TOKEN 为空,请提供" exit 1 fi cat >> /tmp/env_vars.sh << EOF ADMIN_QQ='${ADMIN_QQ}' EOF echo "✅ 变量全部就绪:ADMIN_QQ=$ADMIN_QQ, AGENT=$NEW_AGENT_ID" ``` > 之后每一步 bash 代码块,第一条命令都应是 `source /tmp/env_vars.sh`。 --- ### 第2步:通过 Docker 部署 NapCat NapCat 是 QQ 协议实现,接收 QQ 消息并通过 **HTTP POST** 推送到 qqrebot。 #### 2.1 端口说明 | 端口 | 是否必开 | 用途 | |---|---|---| | `6097` | ✅ | OneBot HTTP API(脚本发消息/群管理/取数据都用此端口) | | `6099` | ✅ | WebUI 管理面板(NapCat 默认占用,不能与 API 共用) | | `3001` | ❌ | WebSocket Server(本教程用 HTTP POST,不启用) | > NapCat v4 的 WebUI 默认绑定端口 6099。OneBot HTTP API 需要独立端口(本教程使用 6097)。 > WebUI 用于扫码登录和管理界面,首次部署时需保持开启;生产环境可关闭或将 WebUI 绑定到 `127.0.0.1`。 #### 2.2 创建目录结构 ```bash source /tmp/env_vars.sh mkdir -p "${SHARED_DIR}" mkdir -p /opt/napcat/config mkdir -p /opt/napcat/qq_data ``` #### 2.3 创建 onebot11.json 配置 > ⚠️ onebot11.json 默认不存在,需手动创建。NapCat v4 使用 `network` 配置格式(非旧版 `http{} ws{}` 格式)。 ```bash source /tmp/env_vars.sh cat > /opt/napcat/config/onebot11.json << ONEBOTEOF { "network": { "httpServers": [ { "name": "http-server", "enable": true, "host": "0.0.0.0", "port": 6097, "token": "", "enableCors": true, "debug": false } ], "httpClients": [ { "name": "http-post", "enable": true, "url": "http://${QQREBOT_HOST}/", "messagePostFormat": "array", "reportSelfMessage": false, "token": "", "debug": false } ], "websocketServers": [], "websocketClients": [] }, "musicSignUrl": "", "enableLocalFile2Url": true, "parseMultMsg": false } ONEBOTEOF ``` > `httpServers`:OneBot HTTP API,脚本通过此端口发送消息/管理群组。 > `httpClients`:NapCat 将消息事件通过 HTTP POST 推送到 qqrebot。 > `httpClients[0].url` 使用 `${QQREBOT_HOST}`,因 heredoc 无引号,bash 自动展开(同机部署时为 `172.17.0.1:25580`)。 **验证:** ```bash source /tmp/env_vars.sh cat /opt/napcat/config/onebot11.json | grep -o 'http://[^"]*' # 预期:http://172.17.0.1:25580/ ``` #### 2.4 启动 NapCat Docker 容器 ```bash source /tmp/env_vars.sh docker run -d \ --name napcat \ --restart unless-stopped \ -p 6097:6097 \ -p 6099:6099 \ -v /opt/napcat/config:/app/napcat/config \ -v /opt/napcat/qq_data:/app/.config/QQ \ -v "${SHARED_DIR}:/app/napcat/share" \ --dns=114.114.114.114 \ mlikiowa/napcat-docker:latest ``` > 必须同时暴露 `6097`(OneBot API)和 `6099`(WebUI),缺一不可。 #### 2.5 QQ 登录(扫码)— ⚠️ 需要人工介入 > ⚠️ **OneBot HTTP API 在 QQ 登录成功之前不会启动!** > **这一步无法由 AI agent 自动完成,必须暂停并请用户操作。** > > agent 行为:打印二维码链接/URL 后**等待用户确认登录成功**,再继续后续步骤。 ```bash # 1) 获取二维码 URL(打印给用户) docker logs napcat 2>&1 | grep -o 'http[s]*://[^ ]*\.png' # 2) 或者告诉用户打开 WebUI echo "" echo "==========================================" echo " 请在浏览器打开以下地址扫码登录 QQ:" echo " http://<服务器IP>:6099/webui" echo "==========================================" echo "" # 3) 💡 agent 应在此处暂停并询问用户是否已登录 # (可选:自动等待登录成功日志) echo "等待登录成功(agent 请等待用户确认后继续)" ``` **验证 HTTP API 可访问:** ```bash # 仅在用户确认登录后可执行 curl -s http://localhost:6097/get_version_info | python3 -m json.tool # 预期:{"status": "ok", "data": {"app_name": "NapCat", ...}, ...} ``` --- ### 第3步:克隆本仓库(确保源码可在后续步骤使用) > ⚠️ **顺序说明:** 本步提前于"部署 qqrebot"和"打包插件",因为后两者都需要本仓库的源码。 > 原序 Step 6.1 的逻辑移动到此。 ```bash source /tmp/env_vars.sh # 确保 git 可用 command -v git &>/dev/null || { apt-get update && apt-get install -y git; } # 克隆本仓库 if [ ! -d /opt/chatrebot_aireply_plug ]; then git clone https://jianfgit.xyz/jianf/chatrebot_aireply_plug.git /opt/chatrebot_aireply_plug else echo "/opt/chatrebot_aireply_plug 已存在,跳过 clone" fi ls /opt/chatrebot_aireply_plug/README.md ``` > 后续步骤使用 `/opt/chatrebot_aireply_plug` 作为仓库根目录。 --- ### 第4步:部署 qqrebot(消息接收器) qqrebot 是 HTTP 服务器,NapCat 将 QQ 消息 POST 到 qqrebot,qqrebot 加载插件处理。 #### 4.1 下载并安装 qqrebot ```bash source /tmp/env_vars.sh command -v wget &>/dev/null || { apt-get update && apt-get install -y wget; } cd /tmp wget https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/archive/chatrebot1.0.tar.gz tar xzf chatrebot1.0.tar.gz mv chat_rebot-connect-with-onebot-standard- /opt/qqrebot cd /opt/qqrebot ``` #### 4.2 检查端口冲突 ```bash source /tmp/env_vars.sh if ss -tlnp | grep -q :25580; then echo "⚠️ 端口 25580 已被占用,请修改为 25581 或其他空闲端口" echo " 修改 qqrebot config.toml 中的 list_port" exit 1 fi ``` #### 4.3 配置 编辑 `config/config.toml`(使用 sed 替换变量): ```bash source /tmp/env_vars.sh cd /opt/qqrebot mkdir -p config cat > config/config.toml << REBOTEOF [app] list_port = 25580 send_url = "http://${NAPCAT_HOST}:${NAPCAT_API_PORT}" [rebot] id = "" [plugins] dir = ["plugins"] REBOTEOF ``` > `send_url` 是 qqrebot 发给插件的 NapCat API 基础地址。 #### 4.4 创建 systemd 服务 ```bash source /tmp/env_vars.sh cat > /etc/systemd/system/qqrebot.service << 'SERVICEEOF' [Unit] Description=QQ Robot After=network.target docker.service Requires=docker.service [Service] Type=simple WorkingDirectory=/opt/qqrebot ExecStart=/opt/qqrebot/run.sh Restart=always RestartSec=3 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target SERVICEEOF systemctl daemon-reload # ⚠️ 先不启动,等插件部署完成后再启 ``` --- ### 第5步:安装 openclaw_bridge 插件 本仓库即 openclaw_bridge 插件的源码,需打包后部署到 qqrebot。 **打包(必须在目标主机上执行,因含 C 扩展):** > ⚠️ **必须使用虚拟环境,严禁 `--break-system-packages`。** > 如果 `python3 -m venv` 报错(如 Debian 未安装 `python3-venv`),先用包管理器安装。 ```bash source /tmp/env_vars.sh cd /opt/chatrebot_aireply_plug # 确保 python3-venv 可用 if ! python3 -m venv --help &>/dev/null; then apt-get update && apt-get install -y python3-venv fi # 创建并激活虚拟环境 python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt python3 package.py # 部署到 qqrebot cp dist/openclaw_bridge.zip /opt/qqrebot/plugins/ ``` **创建插件配置 `/opt/qqrebot/config/openclawbridge/config.toml`:** ```bash source /tmp/env_vars.sh mkdir -p /opt/qqrebot/config/openclawbridge cat > /opt/qqrebot/config/openclawbridge/config.toml << CONFIGEOF [openclaw] gateway_url = "http://127.0.0.1:18789" gateway_token = "${GATEWAY_TOKEN}" allowed_sender = "${ADMIN_QQ}" model = "openclaw/${NEW_AGENT_ID}" agent_id = "${NEW_AGENT_ID}" CONFIGEOF ``` **启动 qqrebot:** ```bash systemctl enable --now qqrebot ``` **验证插件加载:** ```bash journalctl -u qqrebot -f | grep OpenClawBridge ``` 预期输出: ``` Config loaded: url=http://127.0.0.1:18789, allowed=123456789 ``` --- ### 第6步:创建新的 OpenClaw agent 在 `~/.openclaw/openclaw.json` 的 `agents.list` 中添加新 agent: ```bash source /tmp/env_vars.sh AGENT_WORKSPACE="/home/program/${NEW_AGENT_ID}-workspace" mkdir -p "${AGENT_WORKSPACE}/scripts" mkdir -p "${AGENT_WORKSPACE}/skills" mkdir -p "${AGENT_WORKSPACE}/self-workplace" mkdir -p "${AGENT_WORKSPACE}/memory" mkdir -p "${AGENT_WORKSPACE}/files" # 读取当前 OpenClaw 配置 CONFIG_PATH="$HOME/.openclaw/openclaw.json" if [ ! -f "$CONFIG_PATH" ]; then echo "❌ 未找到 OpenClaw 配置:$CONFIG_PATH" exit 1 fi # 检查 agent 是否已存在 python3 -c " import json with open('$CONFIG_PATH') as f: cfg = json.load(f) agents = cfg.setdefault('agents', {}).setdefault('list', []) if not any(a.get('id') == '$NEW_AGENT_ID' for a in agents): agents.append({ 'id': '$NEW_AGENT_ID', 'name': '$NEW_AGENT_ID', 'model': 'kimi/kimi-for-coding', 'workspace': '$AGENT_WORKSPACE' }) with open('$CONFIG_PATH', 'w') as f: json.dump(cfg, f, indent=2) print('agent 已添加') else: print('agent 已存在,跳过') " ``` #### 6.2 部署角色定义文件(AGENTS.md / SOUL.md 等) 将角色模板文件复制到 agent workspace。这些文件定义 agent 的人设、安全红线、越狱防护和内容审查规则。 ```bash source /tmp/env_vars.sh # 模板目录在本仓库 config/agent-templates/ TEMPLATES_DIR="/opt/chatrebot_aireply_plug/config/agent-templates" if [ -d "$TEMPLATES_DIR" ]; then # ─── 自动获取已登录 QQ 的昵称作为 agent 名字 ─── echo "正在获取 QQ 昵称..." AGENT_NAME=$(curl -s -X POST "http://${NAPCAT_HOST}:${NAPCAT_API_PORT}/get_login_info" \ -H "Content-Type: application/json" -d '{}' \ | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('nickname',''))" 2>/dev/null) if [ -z "$AGENT_NAME" ]; then echo "⚠️ 无法获取 QQ 昵称,使用 ADMIN_NAME 代替" AGENT_NAME="${ADMIN_NAME}" else echo "✅ 获取到 QQ 昵称:$AGENT_NAME" fi # ─── 持久化到 env_vars ─── echo "export AGENT_NAME='${AGENT_NAME}'" >> /tmp/env_vars.sh # 复制模板文件(不覆盖已有文件) for f in AGENTS.md SOUL.md IDENTITY.md USER.md TOOLS.md HEARTBEAT.md; do if [ ! -f "${AGENT_WORKSPACE}/${f}" ]; then cp "${TEMPLATES_DIR}/${f}" "${AGENT_WORKSPACE}/${f}" echo "created: ${f}" else echo "跳过(已存在): ${f}" fi done # ─── 替换占位符 ─── cd "${AGENT_WORKSPACE}" sed -i "s/ADMIN_QQ/${ADMIN_QQ}/g" *.md sed -i "s|ADMIN_NAME|${ADMIN_NAME}|g" *.md sed -i "s|ADMIN_GAME_ID|${ADMIN_GAME_ID}|g" *.md sed -i "s|AGENT_WORKSPACE|${AGENT_WORKSPACE}|g" *.md sed -i "s|AGENT_NAME|${AGENT_NAME}|g" *.md echo "✅ 角色文件已部署,占位符已替换(agent 昵称:$AGENT_NAME)" else echo "⚠️ 模板目录不存在:$TEMPLATES_DIR,请确认仓库已克隆到 /opt/chatrebot_aireply_plug" fi ``` > ⚡ `AGENT_NAME` 自动从 NapCat `/get_login_info` 接口获取已登录 QQ 的昵称。获取失败时回退到 `ADMIN_NAME`。 > 其余占位符(`ADMIN_QQ`、`ADMIN_NAME`、`ADMIN_GAME_ID`、`AGENT_WORKSPACE`)由 sed 自动替换为实际值。 > 如需自定义人设,可直接编辑 agent workspace 中的对应 `.md` 文件。 --- ### 第7步:将脚本和 Skills 部署到 agent workspace #### 7.1 复制脚本 ```bash source /tmp/env_vars.sh cp -r /opt/chatrebot_aireply_plug/scripts/* "${AGENT_WORKSPACE}/scripts/" ls "${AGENT_WORKSPACE}/scripts/" | wc -l # 预期输出:26 ``` #### 7.2 复制 Skills ```bash source /tmp/env_vars.sh for SKILL in qq-messenger qq-management qq-resolver qq-napcat-extras mc-query nix-helper browser file-process; do srcdir="/opt/chatrebot_aireply_plug/skills/${SKILL}" if [ -d "$srcdir" ]; then cp -r "$srcdir" "${AGENT_WORKSPACE}/skills/" echo "copied: $SKILL" else echo "⚠️ skill 不存在: $SKILL" fi done ``` #### 7.3 替换占位符 ```bash source /tmp/env_vars.sh # ─── 替换脚本占位符 ─── cd "${AGENT_WORKSPACE}/scripts" sed -i "s|YOUR_NAPCAT_HOST:25570|${NAPCAT_HOST}:${NAPCAT_API_PORT}|g" *.py sed -i "s|YOUR_NAPCAT_HOST|${NAPCAT_HOST}:${NAPCAT_API_PORT}|g" *.py sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" *.py sed -i "s|YOUR_GATEWAY_TOKEN|${GATEWAY_TOKEN}|g" *.py sed -i "s|YOUR_WORKSPACE_PATH|${AGENT_WORKSPACE}|g" *.py sed -i "s|YOUR_SHARED_DIR|${SHARED_DIR}|g" *.py # ─── 替换 Skills 占位符 ─── cd "${AGENT_WORKSPACE}/skills" for f in */SKILL.md; do sed -i "s|YOUR_WORKSPACE_PATH|${AGENT_WORKSPACE}|g" "$f" sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" "$f" sed -i "s|YOUR_SHARED_DIR|${SHARED_DIR}|g" "$f" done ``` #### 7.4 验证完整性 ```bash source /tmp/env_vars.sh echo "scripts: $(ls "${AGENT_WORKSPACE}/scripts/" | wc -l) 个" echo "skills: $(ls "${AGENT_WORKSPACE}/skills/" | wc -l) 个" if grep -r "YOUR_ADMIN_QQ\|YOUR_WORKSPACE_PATH\|YOUR_NAPCAT_HOST\|YOUR_SHARED_DIR\|ADMIN_QQ\|AGENT_WORKSPACE" "${AGENT_WORKSPACE}/"; then echo "⚠️ 还有未替换的占位符!" else echo "✅ 占位符全部替换完毕(含角色模板)" fi ``` --- ### 第8步:重启 OpenClaw Gateway > ⚠️ **重要:在确认已走完前 7 步前,不要执行本步!** > 重启 Gateway 会中断所有正在进行的操作(包括包安装、文件复制等)。 > **本步之前的所有步骤(1-7)必须全部执行完毕。** ```bash source /tmp/env_vars.sh openclaw gateway restart ``` 确认新 agent 已加载: ```bash openclaw config get agents.list # 或 journalctl -u openclaw -f | grep "agent.${NEW_AGENT_ID}" ``` --- ### 第9步:端到端验证 1. 确认 NapCat QQ 已登录(`docker logs napcat 2>&1 | grep "登录成功"`) 2. 确认 OneBot API 可访问(`curl localhost:6097/get_version_info`) 3. 确认 qqrebot 正在运行(`systemctl status qqrebot`) 4. 在 QQ 上给机器人发消息 5. 检查 qqrebot 日志:`journalctl -u qqrebot -f | grep OpenClawBridge` 6. 检查 OpenClaw 日志:`journalctl -u openclaw -f` 7. 验证 agent 已回复 --- ## 脚本适配说明 ### 端口对照 | 组件 | 旧版 go-cqhttp | NapCat(本教程) | |---|---|---| | HTTP API 端口 | `25570` | **6097** | | WebUI | N/A | **6099**(扫码登录用) | | WebSocket | `25570`(兼用) | 不启用 | > 脚本中 `CQHTTP_URL = "http://YOUR_NAPCAT_HOST:25570"` 替换后变为 `http://127.0.0.1:6097`。 ### 文件发送与共享目录 NapCat 运行在 Docker 内部,宿主机文件路径不能直接访问。解决方式: ``` 宿主机 ${SHARED_DIR}/ ⇔ Docker volume → 容器内 /app/napcat/share/ ``` | 脚本 | 关联 | 说明 | |---|---|---| | `qq_send_file.py` | 使用 `TARGET_DIR` | 发文件前复制到共享目录,NapCat 从 `/app/napcat/share/` 读取 | | `qq_ocr_image.py` | 提到 NapCat 回退 | 只在本地 Tesseract 不可用时走 NapCat,此时需文件在共享目录 | | `qq_get_file.py` | 无依赖 | NapCat 返回 base64 或 URL,自动下载,不依赖共享目录 | | `qq_upload_group_file.py` | 无依赖 | 使用 base64:// 编码直接上传,不依赖共享目录 | ### 变量速查 | 占位符 | 替换值 | 出现位置 | |---|---|---| | `YOUR_NAPCAT_HOST:25570` | `${NAPCAT_HOST}:${NAPCAT_API_PORT}` | 所有脚本 | | `YOUR_NAPCAT_HOST` | `${NAPCAT_HOST}:${NAPCAT_API_PORT}` | 部分脚本 | | `YOUR_ADMIN_QQ` | `${ADMIN_QQ}` | 脚本 + SKILL.md | | `YOUR_GATEWAY_TOKEN` | `${GATEWAY_TOKEN}` | 脚本 | | `YOUR_SHARED_DIR` | `${SHARED_DIR}` | `qq_send_file.py`、`qq_ocr_image.py`、`qq-messenger/SKILL.md`、`qq-napcat-extras/SKILL.md` | | `YOUR_WORKSPACE_PATH` | `${AGENT_WORKSPACE}` | SKILL.md + 脚本 | --- ## 安全模块说明 部署完成后,新 agent 将具备以下安全能力(全部在 `src/process.py` 中实现): ### 高危词检测 内置 `HIGH_RISK_WORDS` 词库,覆盖以下类别: | 类别 | 示例关键词 | |---|---| | 越狱/提示词攻击 | `ignore all instructions`、`forget previous` | | 记忆操控 | `delete memory`、`forget everything` | | 敏感信息泄漏 | `sudo password`、`api key` | | 系统命令 | `cat /etc/passwd`、`rm -rf` | **触发时行为:** - 非管理员 → 自动拦截 + 上报管理员 + 该用户加入黑名单 - 管理员 → 记录日志 + 发送告警到 admin 私聊 ### 管理员白名单 | 配置项 | 说明 | |---|---| | `allowed_sender` | 唯一的管理员 QQ 号 | | 非管理员操作 | MC 指令过滤(`/` 开头消息跳过 AI 处理) | ### 消息过滤 - 纯媒体消息(无文字:纯图片/文件/视频)自动跳过 - 系统通知(`[系统通知]`、`[文件回执]`)自动跳过 - 非管理员发送的操作指令(`/` 开头)跳过 AI 处理 ### 安全上报 当非管理员触发高危词时,插件自动通过 NapCat HTTP API 给 `allowed_sender` 发送告警(调用 `send_private_msg`)。 ### 错误脱敏 所有 HTTP 响应体、异常详情不暴露给 QQ 用户,仅记录日志。 ## 配置文件参考 | 配置项 | 必填 | 说明 | |---|---|---| | `gateway_url` | ✅ | OpenClaw Gateway 地址 | | `gateway_token` | ✅ | Gateway 认证 Token | | `allowed_sender` | ✅ | 管理员 QQ 号 | | `model` | ✅ | Agent 模型 ID(格式:`openclaw/${AGENT_ID}`) | | `agent_id` | ✅ | Agent ID(与 `agents.list` 一致) | ## 目录结构 ``` chatrebot_aireply_plug/ ├── config/ │ └── openclawbridge/ │ └── config.toml # 插件配置模板 ├── src/ │ ├── process.py # 插件核心逻辑(含全部安全模块) │ ├── config.toml # 本地测试配置 │ └── modules/ │ ├── plugin_modules.py # BasePlugin + MessageContext │ └── user_module.py # User/Group 封装 ├── scripts/ # ✅ 部署时复制到 agent workspace │ ├── qq_send_msg.py # 发送消息(调 NapCat :6097) │ ├── qq_send_file.py # 发送文件/图片 │ ├── qq_get_groups.py # 获取群列表 │ ├── qq_get_friends.py # 获取好友列表 │ ├── qq_group_manage.py # 群管理(踢/禁言/设管理) │ └── ... ├── skills/ # ✅ 部署时复制到 agent skills/ │ ├── qq-messenger/SKILL.md │ ├── qq-management/SKILL.md │ ├── qq-resolver/SKILL.md │ ├── qq-napcat-extras/SKILL.md │ ├── mc-query/SKILL.md │ └── ... ├── dependence.py ├── package.py ├── packup.sh / packup.bat ├── test.py ├── requirements.txt └── README.md ``` ## 自定义安全词库 编辑 `src/process.py` 中的 `HIGH_RISK_WORDS` 列表后重新打包部署重启: ```python HIGH_RISK_WORDS = { "prompt_injection": ["ignore all instructions", ...], "memory_manipulation": ["delete memory", ...], "info_leak": ["sudo password", ...], "system_commands": ["cat /etc/passwd", ...], } ``` ## 许可证 MIT