refactor: README 重构为 agent 全自动执行流程
解决 5 个自主部署阻塞问题: 1. 🧩 步骤重排 — clone 仓库提前到新 Step 3(原 Step 6.1) 确保 Step 5(打包插件)有源码可用 2. 🔄 变量持久化 — 用 /tmp/env_vars.sh 替代 export 每个 bash 代码块首行加 source,跨 exec 调用变量不丢失 3. 🛠 前置依赖自动检测 — 检查 git/wget/docker/python3-venv 缺失即提示安装,防止脚本跑到一半报错 4. 👷 扫码登录人工介入协议 — 明确标注无法由 AI agent 自动完成 agent 知悉:此处需暂停并请用户操作,确认后再继续 5. 🔑 私有仓库凭据提示 — git clone 和 wget 均标注需 SSH/HTTP 凭据 失败时 agent 应引导用户手动操作
This commit is contained in:
412
README.md
412
README.md
@ -50,13 +50,51 @@ QQ 用户 →→→ NapCat(Docker)
|
||||
|
||||
## 部署步骤(阅读此文档的 AI agent 请按以下顺序执行)
|
||||
|
||||
> ⚠️ **关于变量持久化:** 以下每个步骤中的 bash 代码块可能在独立 shell 中执行。
|
||||
> agent 应**将变量保存到文件**以便跨步骤使用,而不是依赖 `export` 在当前 shell 的生存期。
|
||||
> 建议策略:Step 1 执行后,将导出的变量写入 `/tmp/env_vars.sh`,
|
||||
> 后续每个 bash 块开头先 `source /tmp/env_vars.sh` 恢复环境。
|
||||
|
||||
---
|
||||
|
||||
### 第1步:环境自动检测 + 询问关键信息
|
||||
|
||||
本步骤将自动推导绝大多数配置,**只需向用户确认两个不可推导的值**。
|
||||
|
||||
#### 1.1 设置默认值(agent 自动执行)
|
||||
#### 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
|
||||
# ─── 可自动推导的变量,全部使用默认值 ───
|
||||
@ -85,10 +123,24 @@ 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 << 'VFEOF'
|
||||
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}'
|
||||
VFEOF
|
||||
|
||||
echo "变量已写入 /tmp/env_vars.sh,后续步骤请先 source 该文件"
|
||||
```
|
||||
|
||||
> 变量命名规则:脚本中的占位符为 `YOUR_NAPCAT_HOST:25570`(带端口),由 sed 替换为 `${NAPCAT_HOST}:${NAPCAT_API_PORT}`。请勿在 bash 变量名中使用空格。
|
||||
> `QQREBOT_HOST` 带端口 `:25580`,用于 onebot11.json 的 `httpClients` URL。
|
||||
> ⚠️ 持久化文件 `/tmp/env_vars.sh` 中的 `${}` 使用**单引号 heredoc 包裹**,
|
||||
> 以确保 bash 在当前阶段立即展开(而非写入文字 `${NEW_AGENT_ID}`)。
|
||||
> 后续步骤每次执行 bash 代码块前,应先 `source /tmp/env_vars.sh`。
|
||||
|
||||
#### 1.2 向用户确认
|
||||
|
||||
@ -101,23 +153,32 @@ print(cfg.get('gateway', {}).get('auth', {}).get('token', ''))
|
||||
|
||||
> 其余变量(`NEW_AGENT_ID`、`SHARED_DIR`、`NAPCAT_HOST`、`NAPCAT_API_PORT`、`QQREBOT_HOST`)全部使用默认值即可。仅在跨机部署时需要用户调整 `NAPCAT_HOST` 或 `NAPCAT_API_PORT`。
|
||||
|
||||
#### 1.3 应用变量
|
||||
#### 1.3 获取必填值并持久化
|
||||
|
||||
```bash
|
||||
# 确认必填项
|
||||
# 用户已提供 ADMIN_QQ(由 agent 通过询问获得)
|
||||
# 将该值追加到持久化变量文件
|
||||
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
if [ -z "$ADMIN_QQ" ]; then
|
||||
echo "请提供 ADMIN_QQ"
|
||||
echo "❌ ADMIN_QQ 为空,请提供"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$GATEWAY_TOKEN" ]; then
|
||||
echo "自动读取 GATEWAY_TOKEN 失败,请提供"
|
||||
echo "❌ GATEWAY_TOKEN 为空,请提供"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export ADMIN_QQ NEW_AGENT_ID AGENT_WORKSPACE SHARED_DIR NAPCAT_HOST NAPCAT_API_PORT QQREBOT_HOST GATEWAY_TOKEN
|
||||
echo "变量已就绪:ADMIN_QQ=$ADMIN_QQ, AGENT=$NEW_AGENT_ID, NAPCAT=$NAPCAT_HOST:$NAPCAT_API_PORT"
|
||||
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
|
||||
@ -138,11 +199,9 @@ NapCat 是 QQ 协议实现,接收 QQ 消息并通过 **HTTP POST** 推送到 q
|
||||
#### 2.2 创建目录结构
|
||||
|
||||
```bash
|
||||
# 共享文件目录(NapCat Docker 内发文件时读取)
|
||||
SHARED_DIR="${SHARED_DIR:-/opt/napcat_shared}"
|
||||
mkdir -p "${SHARED_DIR}"
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
# NapCat 配置目录 + QQ 登录数据持久化
|
||||
mkdir -p "${SHARED_DIR}"
|
||||
mkdir -p /opt/napcat/config
|
||||
mkdir -p /opt/napcat/qq_data
|
||||
```
|
||||
@ -152,6 +211,8 @@ mkdir -p /opt/napcat/qq_data
|
||||
> ⚠️ onebot11.json 默认不存在,需手动创建。NapCat v4 使用 `network` 配置格式(非旧版 `http{} ws{}` 格式)。
|
||||
|
||||
```bash
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
cat > /opt/napcat/config/onebot11.json << ONEBOTEOF
|
||||
{
|
||||
"network": {
|
||||
@ -189,11 +250,20 @@ ONEBOTEOF
|
||||
|
||||
> `httpServers`:OneBot HTTP API,脚本通过此端口发送消息/管理群组。
|
||||
> `httpClients`:NapCat 将消息事件通过 HTTP POST 推送到 qqrebot。
|
||||
> `httpClients[0].url` 使用 `${QQREBOT_HOST}`,因 heredoc 无引号,bash 会自动展开为 `172.17.0.1:25580`(Docker bridge 网关 IP)。可通过 `docker network inspect bridge` 确认。
|
||||
> `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 \
|
||||
@ -208,59 +278,91 @@ docker run -d \
|
||||
|
||||
> 必须同时暴露 `6097`(OneBot API)和 `6099`(WebUI),缺一不可。
|
||||
|
||||
#### 2.5 QQ 登录(扫码)
|
||||
#### 2.5 QQ 登录(扫码)— ⚠️ 需要人工介入
|
||||
|
||||
> ⚠️ OneBot HTTP API 在 QQ 登录成功之前不会启动!
|
||||
> `curl /get_version_info` 类 API 调用必须在登录后才能成功。
|
||||
> ⚠️ **OneBot HTTP API 在 QQ 登录成功之前不会启动!**
|
||||
> **这一步无法由 AI agent 自动完成,必须暂停并请用户操作。**
|
||||
>
|
||||
> agent 行为:打印二维码链接/URL 后**等待用户确认登录成功**,再继续后续步骤。
|
||||
|
||||
```bash
|
||||
# 查看登录二维码(日志中会打印链接)
|
||||
# 1) 获取二维码 URL(打印给用户)
|
||||
docker logs napcat 2>&1 | grep -o 'http[s]*://[^ ]*\.png'
|
||||
# 或用浏览器打开 http://<服务器IP>:6099/webui 扫码登录
|
||||
|
||||
# 等待登录成功
|
||||
docker logs napcat -f | grep "登录成功"
|
||||
# 2) 或者告诉用户打开 WebUI
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " 请在浏览器打开以下地址扫码登录 QQ:"
|
||||
echo " http://<服务器IP>:6099/webui"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 登录成功后 OneBot 配置会自动加载,可以看到类似日志:
|
||||
# [Notice] [OneBot11] HTTP服务: 0.0.0.0:6097, : 已启动
|
||||
# [Notice] [OneBot11] HTTP上报服务: http://172.17.0.1:25580/, : 已启动
|
||||
# 3) 💡 agent 应在此处暂停并询问用户是否已登录
|
||||
# (可选:自动等待登录成功日志)
|
||||
echo "等待登录成功(agent 请等待用户确认后继续)"
|
||||
```
|
||||
|
||||
#### 2.6 验证 NapCat
|
||||
**验证 HTTP API 可访问:**
|
||||
|
||||
```bash
|
||||
# 验证 HTTP API 可访问(仅在登录成功后可调用)
|
||||
# 仅在用户确认登录后可执行
|
||||
curl -s http://localhost:6097/get_version_info | python3 -m json.tool
|
||||
|
||||
# 预期输出:
|
||||
# {"status": "ok", "data": {"app_name": "NapCat", ...}, ...}
|
||||
|
||||
# 验证 WebUI 可访问
|
||||
curl -s -o /dev/null -w "%{http_code}" http://localhost:6099/webui
|
||||
# 预期返回 200
|
||||
# 预期:{"status": "ok", "data": {"app_name": "NapCat", ...}, ...}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 第3步:部署 qqrebot(消息接收器)
|
||||
### 第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; }
|
||||
|
||||
# 克隆本仓库
|
||||
# ⚠️ jianfgit.xyz 是私有 Git 服务器,需确保 SSH 密钥已配置
|
||||
# 如果 clone 失败,请用户提供 HTTP 凭据或手动复制
|
||||
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 加载插件处理。
|
||||
|
||||
#### 3.1 安装 qqrebot
|
||||
|
||||
从 [chatrebot1.0 release](https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/src/tag/chatrebot1.0/) 下载:
|
||||
#### 4.1 下载并安装 qqrebot
|
||||
|
||||
```bash
|
||||
source /tmp/env_vars.sh
|
||||
command -v wget &>/dev/null || { apt-get update && apt-get install -y wget; }
|
||||
|
||||
# ⚠️ 链接指向同一私有服务器,需 SSH/HTTP 凭据
|
||||
# 如 wget 失败,请用户手动下载并解压到 /opt/qqrebot
|
||||
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
|
||||
```
|
||||
|
||||
#### 3.2 检查端口冲突
|
||||
#### 4.2 检查端口冲突
|
||||
|
||||
```bash
|
||||
# 检查 25580 是否已被占用
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
if ss -tlnp | grep -q :25580; then
|
||||
echo "⚠️ 端口 25580 已被占用,请修改为 25581 或其他空闲端口"
|
||||
echo " 修改 qqrebot config.toml 中的 list_port"
|
||||
@ -268,30 +370,35 @@ if ss -tlnp | grep -q :25580; then
|
||||
fi
|
||||
```
|
||||
|
||||
#### 3.3 配置
|
||||
#### 4.3 配置
|
||||
|
||||
编辑 `config/config.toml`:
|
||||
编辑 `config/config.toml`(使用 sed 替换变量):
|
||||
|
||||
```toml
|
||||
```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}" # 指向 NapCat OneBot API
|
||||
send_url = "http://${NAPCAT_HOST}:${NAPCAT_API_PORT}"
|
||||
|
||||
[rebot]
|
||||
id = ""
|
||||
|
||||
[plugins]
|
||||
dir = ["plugins"]
|
||||
REBOTEOF
|
||||
```
|
||||
|
||||
> `send_url` 是 qqrebot 框架发给插件的 NapCat API 基础地址(即 `ctx.group.url`)。所有 `send_private_msg` / `send_group_msg` 调用都走此地址。
|
||||
> 如果 NapCat 和 qqrebot 同机,`send_url = "http://127.0.0.1:6097"`。
|
||||
> `send_url` 是 qqrebot 发给插件的 NapCat API 基础地址。
|
||||
|
||||
#### 3.4 创建 systemd 服务
|
||||
#### 4.4 创建 systemd 服务
|
||||
|
||||
```bash
|
||||
# 注意:如果 qqrebot 已有其他实例在运行,请修改端口和服务名
|
||||
# 此处假设使用端口 25580,服务名 qqrebot
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
cat > /etc/systemd/system/qqrebot.service << 'SERVICEEOF'
|
||||
[Unit]
|
||||
@ -313,57 +420,62 @@ WantedBy=multi-user.target
|
||||
SERVICEEOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now qqrebot
|
||||
# ⚠️ 先不启动,等插件部署完成后再启
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 第4步:安装 openclaw_bridge 插件
|
||||
### 第5步:安装 openclaw_bridge 插件
|
||||
|
||||
本仓库即 openclaw_bridge 插件的源码,需打包后部署到 qqrebot。
|
||||
|
||||
**打包(必须在目标主机上执行,因含 C 扩展):**
|
||||
|
||||
> ⚠️ **必须使用虚拟环境,严禁 `--break-system-packages`。**
|
||||
> 如果 `python3 -m venv` 报错(如 Debian 未安装 `python3-venv`),先用包管理器安装:`apt-get install -y python3-venv`。
|
||||
> 如果 `python3 -m venv` 报错(如 Debian 未安装 `python3-venv`),先用包管理器安装。
|
||||
|
||||
```bash
|
||||
cd /path/to/chatrebot_aireply_plug
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
# 确保可以创建虚拟环境(Debian 默认未安装 python3-venv)
|
||||
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
|
||||
|
||||
# 创建并激活虚拟环境(严禁 --break-system-packages)
|
||||
# 创建并激活虚拟环境
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
pip install -r requirements.txt
|
||||
python3 package.py
|
||||
```
|
||||
|
||||
**部署:**
|
||||
|
||||
```bash
|
||||
# 部署到 qqrebot
|
||||
cp dist/openclaw_bridge.zip /opt/qqrebot/plugins/
|
||||
```
|
||||
|
||||
**创建插件配置 `/opt/qqrebot/config/openclawbridge/config.toml`:**
|
||||
|
||||
```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 加载插件:**
|
||||
**启动 qqrebot:**
|
||||
|
||||
```bash
|
||||
systemctl restart qqrebot
|
||||
systemctl enable --now qqrebot
|
||||
```
|
||||
|
||||
**验证插件加载:**
|
||||
@ -379,129 +491,95 @@ Config loaded: url=http://127.0.0.1:18789, allowed=123456789
|
||||
|
||||
---
|
||||
|
||||
### 第5步:创建新的 OpenClaw agent
|
||||
### 第6步:创建新的 OpenClaw agent
|
||||
|
||||
在 `~/.openclaw/openclaw.json` 的 `agents.list` 中添加新 agent:
|
||||
|
||||
```bash
|
||||
AGENT_ID="${NEW_AGENT_ID}"
|
||||
AGENT_WORKSPACE="/home/program/${AGENT_ID}-workspace"
|
||||
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 已存在,跳过')
|
||||
"
|
||||
```
|
||||
|
||||
添加 agent 配置项到 `agents.list`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "${NEW_AGENT_ID}",
|
||||
"name": "${NEW_AGENT_ID}",
|
||||
"model": "kimi/kimi-for-coding",
|
||||
"workspace": "/home/program/${NEW_AGENT_ID}-workspace"
|
||||
}
|
||||
```
|
||||
|
||||
> 通过 `GET /api/config/all` 获取当前配置,找到 `agents.list` 数组执行 push,然后 `POST /api/config/set`。或直接编辑 `~/.openclaw/openclaw.json` 后重启 Gateway。
|
||||
|
||||
---
|
||||
|
||||
### 第6步:获取源码并部署到 agent 的 workspace
|
||||
### 第7步:将脚本和 Skills 部署到 agent workspace
|
||||
|
||||
> agent 需要在目标服务器上获得 chatrebot_aireply_plug 的 `scripts/`(26 个脚本)和 `skills/`(8 个 skill)目录。
|
||||
|
||||
#### 6.1 在目标服务器上克隆仓库
|
||||
#### 7.1 复制脚本
|
||||
|
||||
```bash
|
||||
# 方案 A:git clone
|
||||
git clone https://jianfgit.xyz/jianf/chatrebot_aireply_plug.git /opt/chatrebot_aireply_plug
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
# 方案 B:本机已有 repo,直接复制
|
||||
# cp -r /home/program/pm-workspace /opt/chatrebot_aireply_plug
|
||||
```
|
||||
|
||||
后续步骤假设源码解压到 `/opt/chatrebot_aireply_plug`。
|
||||
|
||||
#### 6.2 复制脚本
|
||||
|
||||
```bash
|
||||
cp -r /opt/chatrebot_aireply_plug/scripts/* "${AGENT_WORKSPACE}/scripts/"
|
||||
ls "${AGENT_WORKSPACE}/scripts/" | wc -l
|
||||
# 预期输出:26
|
||||
```
|
||||
|
||||
脚本清单(26 个),按功能分组:
|
||||
|
||||
| 分组 | 脚本 | 用途 |
|
||||
|---|---|---|
|
||||
| **QQ 消息** | `qq_send_msg.py` | 发送文本消息 |
|
||||
| | `qq_send_file.py` | 发送文件/图片 |
|
||||
| | `qq_upload_group_file.py` | base64 直接上传群文件 |
|
||||
| | `qq_send_like.py` | 点赞 |
|
||||
| | `qq_ocr_image.py` | 图片 OCR 识别 |
|
||||
| **QQ 查询** | `qq_get_groups.py` | 获取群列表 |
|
||||
| | `qq_get_friends.py` | 获取好友列表 |
|
||||
| | `qq_get_group_files.py` | 获取群文件列表 |
|
||||
| | `qq_get_file.py` | 下载文件 |
|
||||
| | `qq_get_history.py` | 拉取历史消息 |
|
||||
| | `qq_resolve_name.py` | QQ号/群号 ↔ 可读名称 |
|
||||
| **QQ 管理** | `qq_group_action.py` | 退群、接受/拒绝群邀请 |
|
||||
| | `qq_group_manage.py` | 群成员管理(踢/禁言等) |
|
||||
| | `qq_friend_action.py` | 删好友、同意/拒绝好友请求 |
|
||||
| **MC 服务器** | `mc_query.py` | 服务器状态查询 |
|
||||
| | `mc_status.py` | 状态(简化版) |
|
||||
| | `mc_players.py` | 玩家信息 |
|
||||
| | `mc_world.py` | 世界详情 |
|
||||
| | `mc_rcon.py` | 远程执行 RCON 命令 |
|
||||
| | `mc_clear_items.py` | 清理掉落物 |
|
||||
| | `mc_config.py` | 服务器配置管理 |
|
||||
| **工具** | `browse.py` | 网页浏览/截图 |
|
||||
| | `file_store_api.py` | 文件存储 API |
|
||||
| | `ask_nix.py` | 向 ops-manager 求助 |
|
||||
| | `qq_video_download.py` | 视频下载 |
|
||||
| | `__init__.py` | 包初始化 |
|
||||
|
||||
#### 6.3 复制 Skills
|
||||
|
||||
Skills 是 agent 的能力描述文件(`SKILL.md`),每个 skill 一个子目录,agent 启动时会加载:
|
||||
#### 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
|
||||
cp -r "/opt/chatrebot_aireply_plug/skills/${SKILL}" "${AGENT_WORKSPACE}/skills/"
|
||||
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
|
||||
```
|
||||
|
||||
> Skills 中的 SKILL.md 通过 `YOUR_WORKSPACE_PATH/scripts/xxx.py` 引用脚本路径。
|
||||
> agent 执行 `subprocess.run` 时,实际调用的是 `${AGENT_WORKSPACE}/scripts/` 下的脚本。
|
||||
|
||||
#### 6.4 替换占位符(关键!必须执行)
|
||||
|
||||
**替换脚本占位符:**
|
||||
#### 7.3 替换占位符
|
||||
|
||||
```bash
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
# ─── 替换脚本占位符 ───
|
||||
cd "${AGENT_WORKSPACE}/scripts"
|
||||
|
||||
# NapCat HTTP API 地址(端口 ${NAPCAT_API_PORT},非旧版 25570)
|
||||
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
|
||||
|
||||
# 管理员 QQ
|
||||
sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" *.py
|
||||
|
||||
# Gateway Token
|
||||
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 占位符:**
|
||||
|
||||
```bash
|
||||
# ─── 替换 Skills 占位符 ───
|
||||
cd "${AGENT_WORKSPACE}/skills"
|
||||
|
||||
for f in */SKILL.md; do
|
||||
@ -511,42 +589,14 @@ for f in */SKILL.md; do
|
||||
done
|
||||
```
|
||||
|
||||
> ⚠️ Skills 的替换很关键:
|
||||
> - `YOUR_WORKSPACE_PATH` → agent 的 subprocess.run 能找到脚本
|
||||
> - `YOUR_SHARED_DIR` → 涉及文件发送的 Skill(qq-messenger、qq-napcat-extras)理解的宿主机共享路径
|
||||
> - 两个 Skill(qq-messenger、qq-napcat-extras)还记录了容器路径 `/app/napcat/share/`,这是一个固定常量,对应 Docker volume `-v SHARED_DIR:/app/napcat/share`。如果修改了 volume 挂载点,需同步修改这些 SKILL.md 和 `qq_send_file.py`、`qq_ocr_image.py` 中的容器路径。
|
||||
|
||||
**文件发送全链路路径转换示意:**
|
||||
|
||||
```
|
||||
agent 工作区 宿主机共享目录 NapCat 容器内
|
||||
/script/file.txt →cp→ /opt/napcat_shared/ ←volume→ /app/napcat/share/
|
||||
↓
|
||||
qq_send_file.py 构造
|
||||
file:///app/napcat/share/file.txt
|
||||
↓
|
||||
NapCat HTTP API → QQ 用户
|
||||
```
|
||||
|
||||
> 代理的思维模型:"我要发文件 → 把文件放到共享目录 → 脚本从共享目录发"。Skill 中提到的"发送文件/图片"都隐含了这一步文件复制。
|
||||
|
||||
**验证文件路径转换:**
|
||||
#### 7.4 验证完整性
|
||||
|
||||
```bash
|
||||
# 确认共享目录存在
|
||||
ls -la "${SHARED_DIR}/"
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
# 手动测试:复制一个文件过去,走 qq_send_file.py
|
||||
echo hello > /tmp/test.txt
|
||||
python3 "${AGENT_WORKSPACE}/scripts/qq_send_file.py" "/tmp/test.txt" --target "${ADMIN_QQ}" --private
|
||||
```
|
||||
|
||||
#### 6.5 验证完整性
|
||||
|
||||
```bash
|
||||
# 脚本数量
|
||||
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" "${AGENT_WORKSPACE}/"; then
|
||||
echo "⚠️ 还有未替换的占位符!"
|
||||
else
|
||||
@ -556,9 +606,11 @@ fi
|
||||
|
||||
---
|
||||
|
||||
### 第7步:重启 OpenClaw Gateway
|
||||
### 第8步:重启 OpenClaw Gateway
|
||||
|
||||
```bash
|
||||
source /tmp/env_vars.sh
|
||||
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
@ -571,7 +623,7 @@ openclaw config get agents.list
|
||||
|
||||
---
|
||||
|
||||
### 第8步:端到端验证
|
||||
### 第9步:端到端验证
|
||||
|
||||
1. 确认 NapCat QQ 已登录(`docker logs napcat 2>&1 | grep "登录成功"`)
|
||||
2. 确认 OneBot API 可访问(`curl localhost:6097/get_version_info`)
|
||||
|
||||
Reference in New Issue
Block a user