Files
rogee 7bf994de88
Build web service image / build (push) Successful in 40s
feat: make Windows Agent configuration GUI-only
2026-09-20 17:25:34 +08:00

132 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WxAgent Control Plane
Go 1.23 控制面与 React 管理端。节点只主动出站连接,控制面不暴露节点端口。
## 本地启动
```bash
cd control-plane
npm --prefix web ci --no-audit --no-fund
npm --prefix web run build
go run ./cmd/wxagent-control-plane
```
启动前设置(单节点兼容写法):
```bash
export WXAGENT_NODE_ID=local-node
export WXAGENT_NODE_TOKEN='local-node-token'
export WXAGENT_WEB_USER=admin
export WXAGENT_WEB_PASSWORD='change-me'
```
多节点/多用户使用 JSON map:
```bash
export WXAGENT_NODE_TOKENS='{"node-a":"token-a","node-b":"token-b"}'
export WXAGENT_WEB_USERS='{"admin":"change-me","auditor":"read-only-password"}'
```
可选:`WXAGENT_CONTROL_PLANE_ADDR`(默认 `127.0.0.1:8090`)、`WXAGENT_CONTROL_PLANE_DATA`(默认 `control-plane-data.json`)。凭据可通过环境变量或 `*_FILE` Secret 文件读取,不写入控制面数据文件和日志。节点的 `remoteConfigurationFile` 仅用于读取预置配置;Windows Agent 不提供命令行修改配置,启动和本机配置必须通过双击 `WxAgent.Tray.exe` 后的“服务设置...”窗口完成。
生产控制面可直接启用 TLS 和节点 mTLS:
可选的 AI Provider 使用 OpenAI-compatible `chat/completions` 接口;密钥只从环境或 Secret 文件读取:
```text
WXAGENT_AI_BASE_URL=https://api.openai.com/v1
WXAGENT_AI_API_KEY_FILE=/run/secrets/ai_api_key
WXAGENT_AI_MODEL=gpt-4o-mini
WXAGENT_AI_TIMEOUT=60s
WXAGENT_AI_SCHEDULER_INTERVAL=5s
```
```text
WXAGENT_CONTROL_PLANE_TLS_CERT_FILE
WXAGENT_CONTROL_PLANE_TLS_KEY_FILE
WXAGENT_MTLS_CLIENT_CA_FILE
WXAGENT_MTLS_REQUIRE_NODE_CERT=true
WXAGENT_MTLS_REVOKED_CERTS_FILE
WXAGENT_NODE_TOKENS_FILE=/run/secrets/node_tokens
WXAGENT_WEB_USERS_FILE=/run/secrets/web_users
```
节点证书按证书原始 DER 的 SHA-256 指纹逐行写入撤销文件;文件读取失败时节点认证拒绝。控制面还提供 `/readyz`,并对数据文件使用单写入者锁、自动轮转备份和任务/事件/审计保留期限。生产示例见 [`compose.production.yml`](./compose.production.yml)。
浏览器访问 `http://127.0.0.1:8090/`,登录后管理节点、任务、白名单事件和审计记录。生产部署必须使用 HTTPS、节点 mTLS 和外部 Secret 文件;本地 HTTP 仅用于显式的私有网络/loopback 集成测试。
远程只读查询使用同一持久化任务队列,返回 `task_id` 后通过 `GET /v1/tasks/{task_id}` 取结果:
```text
POST /v1/reads/sessions { node_id, account_id, idempotency_key, limit?, offset? }
POST /v1/reads/contacts { node_id, account_id, idempotency_key, groups_only, contains?, limit?, offset? }
POST /v1/reads/messages { node_id, account_id, idempotency_key, chat_id, include_content?, limit?, offset? }
```
节点只返回本地已启用且 `identityVerified` 的白名单会话;未授权范围在节点读取前拒绝。`chat_id` 必须使用会话列表返回的稳定会话标识,消息结果是当前微信 UI 可见历史,不是数据库全量历史。联系人查询中的 `chat_id` 使用联系人数据库稳定 ID;所有响应仍受任务结果大小和分页上限约束。
### AI 消息处理
Web 端的“AI 处理”页面用于创建消息处理流程。每个流程绑定一个或多个 `node_id + account_id + chat_id + chat_type` 目标,支持:
- `realtime`:由节点已授权的实时消息事件触发;
- `interval`:由控制面按秒间隔创建 `read-messages` 只读任务;
- `output_schema`:根节点为 `object` 的 JSON Schema,AI 输出会在控制面再次校验;
- `read_message_context`:读取本次有限消息上下文;
- `reply_text`:在流程显式授权后,向来源群聊/私聊创建一个受控 `send-text` 任务。
相关接口:
```text
GET /v1/ai/tools
GET /v1/ai/flows
POST /v1/ai/flows
GET /v1/ai/flows/{flow_id}
PUT /v1/ai/flows/{flow_id}
DELETE /v1/ai/flows/{flow_id}
POST /v1/ai/flows/{flow_id}/run
GET /v1/ai/runs?flow_id=&limit=
```
AI 处理仍受节点本地白名单约束。定时读取的消息范围与普通 `read-messages` 相同,只是当前微信 UI 可见历史,不是数据库全量历史。AI Provider 未配置时流程可以保存,但执行记录会明确失败,不会把消息内容写入普通日志。
## 验证
```bash
cd control-plane
go test ./...
go vet ./...
cd ../control-plane/web
npm run build
cd ../..
./scripts/remote-control-smoke.sh
```
`remote-control-smoke.sh` 会启动一次临时控制面,运行 .NET 节点协议客户端,验证注册、心跳、任务租约、幂等、结果回传和白名单拒绝;不会操作真实微信联系人。
控制面并发/读取任务基线(使用已注册的测试节点,不执行写任务):
```bash
WXAGENT_SCALE_WEB_PASSWORD='<test-password>' \
scripts/control-plane-scale-smoke.py --base-url http://127.0.0.1:8090 \
--node-id node-a --account-id account-a --requests 100 --workers 10
```
`control-plane-data.sh backup`/`restore` 用于停机前后的手工备份和原子恢复;自动备份由 Store 按 `WXAGENT_CONTROL_PLANE_BACKUP_INTERVAL`(默认 5 分钟)产生。当前 JSON 存储使用 active/passive 单写锁,不支持 active-active 多实例共享写入。
## Windows 手工验收
1. 在已登录且未锁定的微信桌面会话中双击 `WxAgent.Tray.exe`;首次运行或托盘菜单“服务设置...”打开后,配置本机监听、凭据、验证模式和自动锁屏。
2. 不使用 `WxAgent.Host serve``--config``remote auth set``remote reporting enable/allow` 或其他命令行配置。`WxAgent.Host doctor``inspect-ui``remote ... show/probe` 仅用于只读诊断。
3. 远程配置若已由部署系统预置,托盘服务读取 `remoteConfigurationFile`;当前不通过命令行修改远程地址、Token、节点 ID 或 reporting 白名单。
4. 仅使用文件传输助手、`Hao 豪``吉祥三宝``消息测试专用群组`做发送/接收验证:先确认目标账号、稳定 chat ID 和文本;Web/HTTP/MCP 写操作仍必须通过现有确认门禁。
5. 在控制面取消任务并验证节点不执行;断开网络后恢复,确认未完成副作用任务显示 `ResultUnconfirmed`,不会自动重放。
未解锁的 Session 0、昵称、PID、窗口句柄和未确认的运行时身份都应视为验收失败;手工验收不得改写微信数据库或绕过安全机制。
## 容器镜像
`.gitea/workflows/build-web-image.yml` 会构建并推送 `git.ipao.vip/<owner>/<repo>` 镜像:主分支额外更新 `latest``v*` 标签额外更新对应版本标签。请在 Gitea 账号级 Secrets 配置 `REGISTRY_TOKEN`;登录用户名使用仓库所有者。
生产环境不要提交 `compose.production.yml` 所引用的 `secrets/` 文件。将节点 Token map、Web 用户 map、TLS 私钥、客户端 CA 和撤销指纹列表放入外部 Secret 管理或受 ACL 保护的部署目录,再运行 `docker compose -f compose.production.yml up -d`。证书泄露时可用 `scripts/revoke-client-certificate.sh` 更新指纹列表,并重建 Docker Secret 挂载的容器。