From c55053710a874d1f47e54667aabe7517cd7500af Mon Sep 17 00:00:00 2001 From: liuwei Date: Thu, 7 May 2026 10:29:03 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=99=BB=E5=BD=95=E6=80=81?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=AD=98=E5=82=A8=E5=88=B0provider=E7=9B=AE?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.docker.example | 3 ++- .env.example | 3 ++- .gitignore | 1 + README.MD | 6 +++--- THIRD_PARTY_LICENSES.md | 2 +- config.example.yaml | 7 ++++--- config.yaml | 7 ++++--- configuration.py | 6 ++---- docker-compose.yml | 6 +++--- docker-entrypoint.sh | 10 +++++----- docs/Docker部署说明.md | 6 +++--- robot.py | 20 ++++++++++++++++++-- wechat_ipad/config.toml.example | 2 ++ 13 files changed, 50 insertions(+), 29 deletions(-) diff --git a/.env.docker.example b/.env.docker.example index 4dc3f12..7f2a485 100644 --- a/.env.docker.example +++ b/.env.docker.example @@ -24,4 +24,5 @@ WECHAT_SERVER_TYPE=legacy_855 WECHAT_WXID= WECHAT_DEVICE_NAME= WECHAT_DEVICE_ID= -WECHAT_STATE_FILE=temp/wechat_ipad/config.toml +# 留空时会默认写到 `wechat_ipad/providers//runtime_state.toml`。 +WECHAT_STATE_FILE= diff --git a/.env.example b/.env.example index 1075790..d07dad5 100644 --- a/.env.example +++ b/.env.example @@ -40,7 +40,8 @@ WECHAT_SERVER_TYPE=legacy_855 WECHAT_WXID= WECHAT_DEVICE_NAME= WECHAT_DEVICE_ID= -WECHAT_STATE_FILE=temp/wechat_ipad/config.toml +# 留空时会默认写到 `wechat_ipad/providers//runtime_state.toml`。 +WECHAT_STATE_FILE= ABOT_LLM_DEFAULT_BACKEND=dify_workflow_chat ABOT_LLM_DIFY_API_BASE_URL=http://127.0.0.1:8080/v1 diff --git a/.gitignore b/.gitignore index c19bfbe..c0fface 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ logs/ .DS_Store temp/ wechat_ipad/config.toml +wechat_ipad/providers/*/runtime_state.toml diff --git a/README.MD b/README.MD index c5537ed..b683d7f 100644 --- a/README.MD +++ b/README.MD @@ -102,7 +102,7 @@ python main.py 登录后的 `wxid / device_id / device_name` 不再要求你手工维护,它们会自动写入本地状态文件: -- 默认路径:`temp/wechat_ipad/config.toml` +- 默认路径:`wechat_ipad/providers//runtime_state.toml` - 可通过 `WECHAT_STATE_FILE` 覆盖 - 启动时会自动兼容历史 `wechat_ipad/config.toml` 中已有的登录态 @@ -137,7 +137,7 @@ abot/ - 应用、MariaDB、Redis 已拆分为独立服务 - 提供 `docker-compose.yml`、`.dockerignore`、`.env.docker.example` - 静态连接配置统一通过 `.env` 注入,更适合开源仓库和多环境部署 -- wechat 登录态缓存单独落到 `temp/wechat_ipad/config.toml` +- wechat 登录态缓存默认落到对应 provider 目录下 当前仍建议你在正式生产前继续补充: @@ -165,7 +165,7 @@ abot/ - `.env` - `config.yaml` -- `temp/wechat_ipad/config.toml` 中的真实 `wxid` / `device_id` +- `wechat_ipad/providers/*/runtime_state.toml` 中的真实 `wxid` / `device_id` - 真实数据库密码、LLM API Key、Webhook Token ## 路线图 diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 7c0d8d0..a786ab6 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -53,6 +53,6 @@ 每次准备公开发布新版本时,至少做一次以下检查: -1. 检查是否误提交 `.env`、`config.yaml`、`temp/wechat_ipad/config.toml` +1. 检查是否误提交 `.env`、`config.yaml`、`wechat_ipad/providers/*/runtime_state.toml` 2. 检查仓库中是否仍包含真实账号、真实 token、真实 webhook 密钥 3. 检查新增的二进制、字体、图片、模板文件是否有明确来源与许可证 diff --git a/config.example.yaml b/config.example.yaml index 9b46686..e02c7e5 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -46,8 +46,9 @@ wx_config: wechat_ipad: # wechat_ipad 静态连接配置统一走环境变量: # 1. 用户只需要维护 `.env`,不必再手工同步独立 TOML; - # 2. 登录态缓存会单独写入 `state_file`,避免把运行期字段混进用户配置; - # 3. `legacy_config_path` 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`。 + # 2. 登录态缓存会单独写入 provider 自己目录下的状态文件,避免把运行期字段混进用户配置; + # 3. `state_file` 留空时会按 `server_type` 自动落到对应 provider 目录; + # 4. `legacy_config_path` 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`。 server_url: "${WECHAT_SERVER_URL:http://127.0.0.1:8059/}" server_ip: "${WECHAT_SERVER_IP:127.0.0.1}" server_port: "${WECHAT_SERVER_PORT:8059}" @@ -55,7 +56,7 @@ wechat_ipad: wxid: "${WECHAT_WXID:}" device_name: "${WECHAT_DEVICE_NAME:}" device_id: "${WECHAT_DEVICE_ID:}" - state_file: "${WECHAT_STATE_FILE:temp/wechat_ipad/config.toml}" + state_file: "${WECHAT_STATE_FILE:}" legacy_config_path: "${WECHAT_LEGACY_CONFIG_PATH:wechat_ipad/config.toml}" llm: diff --git a/config.yaml b/config.yaml index 9b46686..e02c7e5 100644 --- a/config.yaml +++ b/config.yaml @@ -46,8 +46,9 @@ wx_config: wechat_ipad: # wechat_ipad 静态连接配置统一走环境变量: # 1. 用户只需要维护 `.env`,不必再手工同步独立 TOML; - # 2. 登录态缓存会单独写入 `state_file`,避免把运行期字段混进用户配置; - # 3. `legacy_config_path` 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`。 + # 2. 登录态缓存会单独写入 provider 自己目录下的状态文件,避免把运行期字段混进用户配置; + # 3. `state_file` 留空时会按 `server_type` 自动落到对应 provider 目录; + # 4. `legacy_config_path` 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`。 server_url: "${WECHAT_SERVER_URL:http://127.0.0.1:8059/}" server_ip: "${WECHAT_SERVER_IP:127.0.0.1}" server_port: "${WECHAT_SERVER_PORT:8059}" @@ -55,7 +56,7 @@ wechat_ipad: wxid: "${WECHAT_WXID:}" device_name: "${WECHAT_DEVICE_NAME:}" device_id: "${WECHAT_DEVICE_ID:}" - state_file: "${WECHAT_STATE_FILE:temp/wechat_ipad/config.toml}" + state_file: "${WECHAT_STATE_FILE:}" legacy_config_path: "${WECHAT_LEGACY_CONFIG_PATH:wechat_ipad/config.toml}" llm: diff --git a/configuration.py b/configuration.py index eb412d4..4ef6b1a 100644 --- a/configuration.py +++ b/configuration.py @@ -205,7 +205,7 @@ class Config(object): # wechat_ipad 配置归一化: # 1. 静态连接参数现在统一走 config.yaml + .env,而不是要求用户维护独立 TOML; - # 2. 登录后的 wxid / device_id / device_name 会落到本地状态文件,因此这里保留 state_file 配置; + # 2. 登录后的 wxid / device_id / device_name 会落到 provider 自己目录下的本地状态文件; # 3. legacy_config_path 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`,迁移完成后可逐步淡出。 wechat_ipad_config = dict(normalized.get("wechat_ipad", {}) or {}) wechat_ipad_config["server_port"] = self._safe_int(wechat_ipad_config.get("server_port", 8059), 8059) @@ -217,9 +217,7 @@ class Config(object): wechat_ipad_config["wxid"] = str(wechat_ipad_config.get("wxid", "") or "").strip() wechat_ipad_config["device_name"] = str(wechat_ipad_config.get("device_name", "") or "").strip() wechat_ipad_config["device_id"] = str(wechat_ipad_config.get("device_id", "") or "").strip() - wechat_ipad_config["state_file"] = str( - wechat_ipad_config.get("state_file", "temp/wechat_ipad/config.toml") or "temp/wechat_ipad/config.toml" - ).strip() + wechat_ipad_config["state_file"] = str(wechat_ipad_config.get("state_file", "") or "").strip() wechat_ipad_config["legacy_config_path"] = str( wechat_ipad_config.get("legacy_config_path", "wechat_ipad/config.toml") or "wechat_ipad/config.toml" ).strip() diff --git a/docker-compose.yml b/docker-compose.yml index d191e22..5eb12c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,14 +84,14 @@ services: WECHAT_WXID: ${WECHAT_WXID:-} WECHAT_DEVICE_NAME: ${WECHAT_DEVICE_NAME:-} WECHAT_DEVICE_ID: ${WECHAT_DEVICE_ID:-} - WECHAT_STATE_FILE: ${WECHAT_STATE_FILE:-temp/wechat_ipad/config.toml} + WECHAT_STATE_FILE: ${WECHAT_STATE_FILE:-} ports: - "${DASHBOARD_PORT:-8888}:8888" volumes: # 日志目录映射到宿主机,方便排障与运维备份。 - ./logs:/app/logs - # 保留 wechat_ipad 的本地登录态缓存,避免容器重建后丢失 wxid / device 信息。 - - ./temp:/app/temp + # 保留 provider 目录下的本地登录态缓存,避免容器重建后丢失 wxid / device 信息。 + - ./wechat_ipad/providers:/app/wechat_ipad/providers extra_hosts: # 兼容 Linux 环境下通过 host.docker.internal 访问宿主机上的 wechat_ipad server。 - "host.docker.internal:host-gateway" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index e73816b..43d0cb9 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -55,15 +55,15 @@ wechat_ipad: wxid: "\${WECHAT_WXID:}" device_name: "\${WECHAT_DEVICE_NAME:}" device_id: "\${WECHAT_DEVICE_ID:}" - state_file: "\${WECHAT_STATE_FILE:temp/wechat_ipad/config.toml}" + state_file: "\${WECHAT_STATE_FILE:}" legacy_config_path: "\${WECHAT_LEGACY_CONFIG_PATH:wechat_ipad/config.toml}" EOF fi -# wechat_ipad 登录态现在单独落到本地状态目录: +# wechat_ipad 登录态现在默认落到 provider 自己目录下: # 1. 静态连接配置已统一走 `.env` / `config.yaml`; -# 2. 这里只需要保证状态文件目录存在,供运行期自动写入 wxid / device 缓存; -# 3. 这样容器启动脚本不再负责生成和维护第二份静态配置文件。 -mkdir -p /app/temp/wechat_ipad +# 2. 855 当前默认会写到 `wechat_ipad/providers/legacy_855/runtime_state.toml`; +# 3. 这里只预创建 provider 根目录,真正状态文件由运行期按 provider 自动写入。 +mkdir -p /app/wechat_ipad/providers exec "$@" diff --git a/docs/Docker部署说明.md b/docs/Docker部署说明.md index 326715b..9c35d8e 100644 --- a/docs/Docker部署说明.md +++ b/docs/Docker部署说明.md @@ -63,8 +63,8 @@ docker compose up -d --build 登录后的 `wxid / device_id / device_name` 会自动写入本地状态缓存: -- 默认路径:`temp/wechat_ipad/config.toml` -- Compose 已将宿主机的 `./temp` 目录映射进容器 +- 默认路径:`wechat_ipad/providers//runtime_state.toml` +- Compose 已将宿主机的 `./wechat_ipad/providers` 目录映射进容器 - 因此容器重建后,已有登录态仍会保留 兼容说明: @@ -116,5 +116,5 @@ docker compose up -d --build 1. `.env` 未提交 2. `config.yaml` 未提交真实密钥 -3. `temp/wechat_ipad/config.toml` 未被误公开 +3. `wechat_ipad/providers/*/runtime_state.toml` 未被误公开 4. Dashboard 账号密码与 webhook token 已替换为你自己的值 diff --git a/robot.py b/robot.py index 4517b43..219fdc6 100644 --- a/robot.py +++ b/robot.py @@ -278,7 +278,9 @@ class Robot: # 3. 这样未来切到 864 时,主链路只需要替换 provider,而不是继续改这里的大循环。 await self.ipad_bot.run_runtime( ipad_config=self.ipad_config, - state_path=str(self.ipad_config.get("state_file", "temp/wechat_ipad/config.toml") or "temp/wechat_ipad/config.toml"), + state_path=str( + self.ipad_config.get("state_file", "") or self._default_wechat_state_path(self.ipad_config) + ), logger=self.LOG, on_login_ready=self._on_ipad_login_ready, on_history_message=self._archive_startup_history_message, @@ -301,7 +303,7 @@ class Robot: 3. 最后兼容历史 `wechat_ipad/config.toml`,让老环境升级后可以平滑迁移。 """ base_config = dict(getattr(self.config, "wechat_ipad", {}) or {}) - state_path = str(base_config.get("state_file", "temp/wechat_ipad/config.toml") or "temp/wechat_ipad/config.toml") + state_path = str(base_config.get("state_file", "") or self._default_wechat_state_path(base_config)) legacy_config_path = str( base_config.get("legacy_config_path", "wechat_ipad/config.toml") or "wechat_ipad/config.toml" ) @@ -341,6 +343,20 @@ class Robot: merged_config["legacy_config_path"] = legacy_config_path return merged_config + @staticmethod + def _default_wechat_state_path(ipad_config: dict) -> str: + """根据当前 provider 类型返回默认的本地状态文件路径。 + + 设计原因: + 1. 用户希望登录态跟随 provider 放置,避免散落在 `temp/` 目录中; + 2. 后续新增 864 等 provider 时,可以天然形成“每个 provider 自己维护自己的状态”; + 3. 这里统一在主程序收口默认路径,避免把路径规则写散到文档、脚本和 provider 内部。 + """ + server_type = str(ipad_config.get("server_type", "legacy_855") or "legacy_855").strip().lower() + if not server_type: + server_type = "legacy_855" + return os.path.join("wechat_ipad", "providers", server_type, "runtime_state.toml") + def _load_toml_config_if_exists(self, file_path: str) -> dict: """安全读取一个 TOML 文件,缺失或格式异常时回退为空配置。""" normalized_path = str(file_path or "").strip() diff --git a/wechat_ipad/config.toml.example b/wechat_ipad/config.toml.example index 9d0f4b2..26609ff 100644 --- a/wechat_ipad/config.toml.example +++ b/wechat_ipad/config.toml.example @@ -2,6 +2,8 @@ server_url = "http://127.0.0.1:8059/" server_ip = "127.0.0.1" server_port = "8059" server_type = "legacy_855" +# 登录成功后的动态状态默认不再写回本文件, +# 而是写到 `wechat_ipad/providers//runtime_state.toml`。 wxid = "" device_id = "" device_name = ""