调整登录态默认存储到provider目录

This commit is contained in:
liuwei
2026-05-07 10:29:03 +08:00
parent d0acd33b66
commit c55053710a
13 changed files with 50 additions and 29 deletions

View File

@@ -24,4 +24,5 @@ WECHAT_SERVER_TYPE=legacy_855
WECHAT_WXID= WECHAT_WXID=
WECHAT_DEVICE_NAME= WECHAT_DEVICE_NAME=
WECHAT_DEVICE_ID= WECHAT_DEVICE_ID=
WECHAT_STATE_FILE=temp/wechat_ipad/config.toml # 留空时会默认写到 `wechat_ipad/providers/<server_type>/runtime_state.toml`。
WECHAT_STATE_FILE=

View File

@@ -40,7 +40,8 @@ WECHAT_SERVER_TYPE=legacy_855
WECHAT_WXID= WECHAT_WXID=
WECHAT_DEVICE_NAME= WECHAT_DEVICE_NAME=
WECHAT_DEVICE_ID= WECHAT_DEVICE_ID=
WECHAT_STATE_FILE=temp/wechat_ipad/config.toml # 留空时会默认写到 `wechat_ipad/providers/<server_type>/runtime_state.toml`。
WECHAT_STATE_FILE=
ABOT_LLM_DEFAULT_BACKEND=dify_workflow_chat ABOT_LLM_DEFAULT_BACKEND=dify_workflow_chat
ABOT_LLM_DIFY_API_BASE_URL=http://127.0.0.1:8080/v1 ABOT_LLM_DIFY_API_BASE_URL=http://127.0.0.1:8080/v1

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ logs/
.DS_Store .DS_Store
temp/ temp/
wechat_ipad/config.toml wechat_ipad/config.toml
wechat_ipad/providers/*/runtime_state.toml

View File

@@ -102,7 +102,7 @@ python main.py
登录后的 `wxid / device_id / device_name` 不再要求你手工维护,它们会自动写入本地状态文件: 登录后的 `wxid / device_id / device_name` 不再要求你手工维护,它们会自动写入本地状态文件:
- 默认路径:`temp/wechat_ipad/config.toml` - 默认路径:`wechat_ipad/providers/<server_type>/runtime_state.toml`
- 可通过 `WECHAT_STATE_FILE` 覆盖 - 可通过 `WECHAT_STATE_FILE` 覆盖
- 启动时会自动兼容历史 `wechat_ipad/config.toml` 中已有的登录态 - 启动时会自动兼容历史 `wechat_ipad/config.toml` 中已有的登录态
@@ -137,7 +137,7 @@ abot/
- 应用、MariaDB、Redis 已拆分为独立服务 - 应用、MariaDB、Redis 已拆分为独立服务
- 提供 `docker-compose.yml`、`.dockerignore`、`.env.docker.example` - 提供 `docker-compose.yml`、`.dockerignore`、`.env.docker.example`
- 静态连接配置统一通过 `.env` 注入,更适合开源仓库和多环境部署 - 静态连接配置统一通过 `.env` 注入,更适合开源仓库和多环境部署
- wechat 登录态缓存单独落到 `temp/wechat_ipad/config.toml` - wechat 登录态缓存默认落到对应 provider 目录下
当前仍建议你在正式生产前继续补充: 当前仍建议你在正式生产前继续补充:
@@ -165,7 +165,7 @@ abot/
- `.env` - `.env`
- `config.yaml` - `config.yaml`
- `temp/wechat_ipad/config.toml` 中的真实 `wxid` / `device_id` - `wechat_ipad/providers/*/runtime_state.toml` 中的真实 `wxid` / `device_id`
- 真实数据库密码、LLM API Key、Webhook Token - 真实数据库密码、LLM API Key、Webhook Token
## 路线图 ## 路线图

View File

@@ -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 密钥 2. 检查仓库中是否仍包含真实账号、真实 token、真实 webhook 密钥
3. 检查新增的二进制、字体、图片、模板文件是否有明确来源与许可证 3. 检查新增的二进制、字体、图片、模板文件是否有明确来源与许可证

View File

@@ -46,8 +46,9 @@ wx_config:
wechat_ipad: wechat_ipad:
# wechat_ipad 静态连接配置统一走环境变量: # wechat_ipad 静态连接配置统一走环境变量:
# 1. 用户只需要维护 `.env`,不必再手工同步独立 TOML # 1. 用户只需要维护 `.env`,不必再手工同步独立 TOML
# 2. 登录态缓存会单独写入 `state_file`,避免把运行期字段混进用户配置; # 2. 登录态缓存会单独写入 provider 自己目录下的状态文件,避免把运行期字段混进用户配置;
# 3. `legacy_config_path` 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`。 # 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_url: "${WECHAT_SERVER_URL:http://127.0.0.1:8059/}"
server_ip: "${WECHAT_SERVER_IP:127.0.0.1}" server_ip: "${WECHAT_SERVER_IP:127.0.0.1}"
server_port: "${WECHAT_SERVER_PORT:8059}" server_port: "${WECHAT_SERVER_PORT:8059}"
@@ -55,7 +56,7 @@ wechat_ipad:
wxid: "${WECHAT_WXID:}" wxid: "${WECHAT_WXID:}"
device_name: "${WECHAT_DEVICE_NAME:}" device_name: "${WECHAT_DEVICE_NAME:}"
device_id: "${WECHAT_DEVICE_ID:}" 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}" legacy_config_path: "${WECHAT_LEGACY_CONFIG_PATH:wechat_ipad/config.toml}"
llm: llm:

View File

@@ -46,8 +46,9 @@ wx_config:
wechat_ipad: wechat_ipad:
# wechat_ipad 静态连接配置统一走环境变量: # wechat_ipad 静态连接配置统一走环境变量:
# 1. 用户只需要维护 `.env`,不必再手工同步独立 TOML # 1. 用户只需要维护 `.env`,不必再手工同步独立 TOML
# 2. 登录态缓存会单独写入 `state_file`,避免把运行期字段混进用户配置; # 2. 登录态缓存会单独写入 provider 自己目录下的状态文件,避免把运行期字段混进用户配置;
# 3. `legacy_config_path` 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`。 # 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_url: "${WECHAT_SERVER_URL:http://127.0.0.1:8059/}"
server_ip: "${WECHAT_SERVER_IP:127.0.0.1}" server_ip: "${WECHAT_SERVER_IP:127.0.0.1}"
server_port: "${WECHAT_SERVER_PORT:8059}" server_port: "${WECHAT_SERVER_PORT:8059}"
@@ -55,7 +56,7 @@ wechat_ipad:
wxid: "${WECHAT_WXID:}" wxid: "${WECHAT_WXID:}"
device_name: "${WECHAT_DEVICE_NAME:}" device_name: "${WECHAT_DEVICE_NAME:}"
device_id: "${WECHAT_DEVICE_ID:}" 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}" legacy_config_path: "${WECHAT_LEGACY_CONFIG_PATH:wechat_ipad/config.toml}"
llm: llm:

View File

@@ -205,7 +205,7 @@ class Config(object):
# wechat_ipad 配置归一化: # wechat_ipad 配置归一化:
# 1. 静态连接参数现在统一走 config.yaml + .env而不是要求用户维护独立 TOML # 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`,迁移完成后可逐步淡出。 # 3. legacy_config_path 仅用于兼容历史仓库中的 `wechat_ipad/config.toml`,迁移完成后可逐步淡出。
wechat_ipad_config = dict(normalized.get("wechat_ipad", {}) or {}) 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) 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["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_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["device_id"] = str(wechat_ipad_config.get("device_id", "") or "").strip()
wechat_ipad_config["state_file"] = str( wechat_ipad_config["state_file"] = str(wechat_ipad_config.get("state_file", "") or "").strip()
wechat_ipad_config.get("state_file", "temp/wechat_ipad/config.toml") or "temp/wechat_ipad/config.toml"
).strip()
wechat_ipad_config["legacy_config_path"] = str( wechat_ipad_config["legacy_config_path"] = str(
wechat_ipad_config.get("legacy_config_path", "wechat_ipad/config.toml") or "wechat_ipad/config.toml" wechat_ipad_config.get("legacy_config_path", "wechat_ipad/config.toml") or "wechat_ipad/config.toml"
).strip() ).strip()

View File

@@ -84,14 +84,14 @@ services:
WECHAT_WXID: ${WECHAT_WXID:-} WECHAT_WXID: ${WECHAT_WXID:-}
WECHAT_DEVICE_NAME: ${WECHAT_DEVICE_NAME:-} WECHAT_DEVICE_NAME: ${WECHAT_DEVICE_NAME:-}
WECHAT_DEVICE_ID: ${WECHAT_DEVICE_ID:-} WECHAT_DEVICE_ID: ${WECHAT_DEVICE_ID:-}
WECHAT_STATE_FILE: ${WECHAT_STATE_FILE:-temp/wechat_ipad/config.toml} WECHAT_STATE_FILE: ${WECHAT_STATE_FILE:-}
ports: ports:
- "${DASHBOARD_PORT:-8888}:8888" - "${DASHBOARD_PORT:-8888}:8888"
volumes: volumes:
# 日志目录映射到宿主机,方便排障与运维备份。 # 日志目录映射到宿主机,方便排障与运维备份。
- ./logs:/app/logs - ./logs:/app/logs
# 保留 wechat_ipad 的本地登录态缓存,避免容器重建后丢失 wxid / device 信息。 # 保留 provider 目录下的本地登录态缓存,避免容器重建后丢失 wxid / device 信息。
- ./temp:/app/temp - ./wechat_ipad/providers:/app/wechat_ipad/providers
extra_hosts: extra_hosts:
# 兼容 Linux 环境下通过 host.docker.internal 访问宿主机上的 wechat_ipad server。 # 兼容 Linux 环境下通过 host.docker.internal 访问宿主机上的 wechat_ipad server。
- "host.docker.internal:host-gateway" - "host.docker.internal:host-gateway"

View File

@@ -55,15 +55,15 @@ wechat_ipad:
wxid: "\${WECHAT_WXID:}" wxid: "\${WECHAT_WXID:}"
device_name: "\${WECHAT_DEVICE_NAME:}" device_name: "\${WECHAT_DEVICE_NAME:}"
device_id: "\${WECHAT_DEVICE_ID:}" 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}" legacy_config_path: "\${WECHAT_LEGACY_CONFIG_PATH:wechat_ipad/config.toml}"
EOF EOF
fi fi
# wechat_ipad 登录态现在单独落到本地状态目录: # wechat_ipad 登录态现在默认落到 provider 自己目录
# 1. 静态连接配置已统一走 `.env` / `config.yaml` # 1. 静态连接配置已统一走 `.env` / `config.yaml`
# 2. 这里只需要保证状态文件目录存在,供运行期自动写入 wxid / device 缓存 # 2. 855 当前默认会写到 `wechat_ipad/providers/legacy_855/runtime_state.toml`
# 3. 这样容器启动脚本不再负责生成和维护第二份静态配置文件 # 3. 这里只预创建 provider 根目录,真正状态文件由运行期按 provider 自动写入
mkdir -p /app/temp/wechat_ipad mkdir -p /app/wechat_ipad/providers
exec "$@" exec "$@"

View File

@@ -63,8 +63,8 @@ docker compose up -d --build
登录后的 `wxid / device_id / device_name` 会自动写入本地状态缓存: 登录后的 `wxid / device_id / device_name` 会自动写入本地状态缓存:
- 默认路径:`temp/wechat_ipad/config.toml` - 默认路径:`wechat_ipad/providers/<server_type>/runtime_state.toml`
- Compose 已将宿主机的 `./temp` 目录映射进容器 - Compose 已将宿主机的 `./wechat_ipad/providers` 目录映射进容器
- 因此容器重建后,已有登录态仍会保留 - 因此容器重建后,已有登录态仍会保留
兼容说明: 兼容说明:
@@ -116,5 +116,5 @@ docker compose up -d --build
1. `.env` 未提交 1. `.env` 未提交
2. `config.yaml` 未提交真实密钥 2. `config.yaml` 未提交真实密钥
3. `temp/wechat_ipad/config.toml` 未被误公开 3. `wechat_ipad/providers/*/runtime_state.toml` 未被误公开
4. Dashboard 账号密码与 webhook token 已替换为你自己的值 4. Dashboard 账号密码与 webhook token 已替换为你自己的值

View File

@@ -278,7 +278,9 @@ class Robot:
# 3. 这样未来切到 864 时,主链路只需要替换 provider而不是继续改这里的大循环。 # 3. 这样未来切到 864 时,主链路只需要替换 provider而不是继续改这里的大循环。
await self.ipad_bot.run_runtime( await self.ipad_bot.run_runtime(
ipad_config=self.ipad_config, 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, logger=self.LOG,
on_login_ready=self._on_ipad_login_ready, on_login_ready=self._on_ipad_login_ready,
on_history_message=self._archive_startup_history_message, on_history_message=self._archive_startup_history_message,
@@ -301,7 +303,7 @@ class Robot:
3. 最后兼容历史 `wechat_ipad/config.toml`,让老环境升级后可以平滑迁移。 3. 最后兼容历史 `wechat_ipad/config.toml`,让老环境升级后可以平滑迁移。
""" """
base_config = dict(getattr(self.config, "wechat_ipad", {}) or {}) 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( legacy_config_path = str(
base_config.get("legacy_config_path", "wechat_ipad/config.toml") or "wechat_ipad/config.toml" 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 merged_config["legacy_config_path"] = legacy_config_path
return merged_config 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: def _load_toml_config_if_exists(self, file_path: str) -> dict:
"""安全读取一个 TOML 文件,缺失或格式异常时回退为空配置。""" """安全读取一个 TOML 文件,缺失或格式异常时回退为空配置。"""
normalized_path = str(file_path or "").strip() normalized_path = str(file_path or "").strip()

View File

@@ -2,6 +2,8 @@ server_url = "http://127.0.0.1:8059/"
server_ip = "127.0.0.1" server_ip = "127.0.0.1"
server_port = "8059" server_port = "8059"
server_type = "legacy_855" server_type = "legacy_855"
# 登录成功后的动态状态默认不再写回本文件,
# 而是写到 `wechat_ipad/providers/<server_type>/runtime_state.toml`。
wxid = "" wxid = ""
device_id = "" device_id = ""
device_name = "" device_name = ""