feat: store packaged user data under data directory

This commit is contained in:
chengma
2026-07-07 14:12:32 +08:00
parent caa04a9aa7
commit 148c4a73eb
33 changed files with 602 additions and 196 deletions
+5 -4
View File
@@ -9,11 +9,12 @@
> **v3.1 修订(2026-07-04,实现前澄清)**:当时为保护既有直连流程,要求全新配置默认 backend 为 `direct`(cmhub 显式 opt-in),且 `backend=cmhub` 但未配置时须抛清晰"去⑤配置"错误而非崩溃(见 §4.1);② 明确"返回值不变"≠"回调不变"——计费元数据须给 `gen_title`/`gen_cover` **新增可选事件回调参数**承载,是向后兼容加参(见 §4.2)。默认策略已被 v3.3/T-529 覆盖为普通产品默认 cmhub。
> **v3.2 修订(2026-07-04,同步对接文档新增)**:cmhub 新增第 4 个接口 `GET /api/v1/models`(别名自助发现,见 §4.6),⑤设置别名由手填改为**动态下拉**(按 `operation_type` 分生文/生图、过滤 `unpriced`、展示单价、`requires_image` 提示),关闭原待确认 #1;仅 Base URL 仍待部署方提供。
> **v3.3 修订(2026-07-04,产品收口)**:普通用户后续默认使用 `cmhub` 网关;⑤设置页去掉「AI 后端」label 和 direct/cmhub 下拉,直接展示 cmhub 网关配置。`direct` 代码和 `config/ai_models.json` 保留为内部兼容/手工回滚路径,但普通 UI 不提供切换入口;保存设置固定写 `ai.backend=cmhub`,允许先保存不完整 cmhub 配置,②生成时再提示去⑤补齐 Base URL/API Key/别名。已同步 T-529。
> **v3.4 修订(2026-07-07,T-538 路径收敛)**:打包版和源码运行的用户数据统一落在 `data/` 下;本文早期提到的 `config.json`、`config/ai_models.json`、`config/cmhub.json`、`images/`,当前默认路径分别为 `data/config.json`、`data/config/ai_models.json`、`data/config/cmhub.json`、`data/images/`。文件名和 schema 不变,旧布局由启动迁移逻辑处理。
> **v3.4 核对(2026-07-06,刷新别名 notfound)**:核对对接文档 §4.4 与 cmhub `ModelsView` 路由,确认 cmshopee `GET /api/v1/models` + Bearer 请求**已达标**;「notfound」为 404,根因是 Base URL 带多余 `/api(/v1)` 路径(双拼)或所连实例未部署 `/api/v1/models`(见 `docs/troubleshooting.md`)。**T-530 已落地**:保存/请求前规整 Base URL 到网关根,HTTP 404 映射为 `not_found` 并给出中文排障提示。
## 1. 背景与目标
**现状**:`app/ai.py` 直连多个上游 provider——每个模型在 `config/ai_models.json` 配 `url/model/api_key/api_type`,`gen_title` 自拼 chat `messages` 解析文本,`gen_cover` 走 `images_edits` multipart 或 vision chat 直接拿图片字节本地存。
**现状**:`app/ai.py` 支持 cmhub 网关和 direct 兼容路径。direct 模式下每个模型在 `data/config/ai_models.json` 配 `url/model/api_key/api_type`,`gen_title` 自拼 chat `messages` 解析文本,`gen_cover` 走 `images_edits` multipart 或 vision chat 直接拿图片字节本地存。
**目标**:改为对接 cmhub 的生成、余额和模型发现接口:`POST /api/v1/generate/title`、`POST /api/v1/generate/image`、`GET /api/v1/balance`、`GET /api/v1/models`,一把 `Authorization: Bearer <API_KEY>` 即可调用。上游 provider、密钥、计费、SSRF 防护、分辨率映射、对象存储与别名发现由 cmhub 承担。
@@ -39,7 +40,7 @@
## 3. 设计原则与边界
- **接缝最小化**:保持 `gen_title(...)` / `gen_cover(...)` 的**返回值与现有调用兼容**(`gen_title`→标题字符串、`gen_cover`→已存 JPEG 路径),允许向后兼容新增可选事件回调参数承载计费元数据,只改内层实现。这样 `generate_batch` 编排、并发、重试、DB 写入、诊断日志、JPEG 落盘、`images/<batch_id>/<slug>/...` 路径、T-520 封面开关**全部复用、零改动**;GUI `run_logs` 记录和余额展示放到 T-528。
- **接缝最小化**:保持 `gen_title(...)` / `gen_cover(...)` 的**返回值与现有调用兼容**(`gen_title`→标题字符串、`gen_cover`→已存 JPEG 路径),允许向后兼容新增可选事件回调参数承载计费元数据,只改内层实现。这样 `generate_batch` 编排、并发、重试、DB 写入、诊断日志、JPEG 落盘、`data/images/<batch_id>/<slug>/...` 路径、T-520 封面开关**全部复用、零改动**;GUI `run_logs` 记录和余额展示放到 T-528。
- **不碰高风险层**:`editor.py`/`cdp.py`/`chrome.py`/`accounts.py`/`excel.py`/`db.py`/`workers.py`,以及 ①采集/③更新/④账号全流程**完全不动**。这是本改动最重要的安全边界。
- **产品默认 cmhub,direct 保留兼容**:内层仍抽 `backend`(`cmhub` / `direct`),但普通产品默认走 `cmhub`,⑤设置页不再展示后端切换。老 `ai_models.json` 和 direct 分支不删除,作为内部兼容/手工回滚路径;普通用户只配置 cmhub Base URL / Key / 别名。
@@ -64,7 +65,7 @@
}
```
- **cmhub API Key 不进 `config.json`**(避免与其它设置混放、避免误提交)。固定存到 `config/cmhub.json`,文件 schema 第一版为 `{ "api_key": "sk_cmhub_xxx" }`;新增 `CMHUB_CONFIG_PATH`、`load_cmhub_config()`、`save_cmhub_config()`、`get_cmhub_api_key(masked=False)` 等 helper;`config/cmhub.json` 必须加入 `.gitignore`。沿用现有"本地明文保存但 gitignore + UI 打码 + 日志脱敏"纪律(T-503)。
- **cmhub API Key 不进 `data/config.json`**(避免与其它设置混放、避免误提交)。固定存到 `data/config/cmhub.json`,文件 schema 第一版为 `{ "api_key": "sk_cmhub_xxx" }`;新增 `CMHUB_CONFIG_PATH`、`load_cmhub_config()`、`save_cmhub_config()`、`get_cmhub_api_key(masked=False)` 等 helper;`data/config/cmhub.json` 必须加入 `.gitignore`。沿用现有"本地明文保存但 gitignore + UI 打码 + 日志脱敏"纪律(T-503)。
- **`ai_models.json` 去留**:`direct` 模式继续用;`cmhub` 模式不读它。文件保留但标记 legacy。
- **默认 backend 与配置不完整处理(T-529 后)**:`DEFAULT_CONFIG` / `default_config()` 造全新配置时写 `backend=cmhub`;⑤设置页隐藏 direct/cmhub 下拉并固定保存 `backend=cmhub`。允许先保存不完整 cmhub 配置,便于用户先保存其它路径/安全设置;②生成真正调用时如果 `base_url`/Key/别名缺失,必须抛**清晰的"请去⑤配置 cmhub"错误**(`CMHubError`/`AIError`),不得崩溃或静默回退 direct。显式手工配置 `backend=direct` 仍作为内部回滚路径保留,但普通 UI 不提供入口。
- **Base URL 必须是网关根**:只填 `https://<cmhub-域名>`,**不带** `/api`、`/api/v1` 或任何路径。`cmhub_request_url()` 会自行拼 `/api/v1/...`;若 Base URL 已含 `/api/v1`,会双拼成 `.../api/v1/api/v1/...` → 404(正是「刷新别名 notfound」现象,见 `docs/troubleshooting.md`)。**当前请求本身已达标**(`GET /api/v1/models` + `Authorization: Bearer <key>`,对齐对接文档 §4.4 与 cmhub `ModelsView` 路由);404 的根因是 Base URL 带多余路径或所连实例未部署 `/api/v1/models`。**T-530 已在保存/请求前规整 Base URL**,会去掉多余路径、查询串和片段,只保留 scheme+host(+port);404 会给出明确中文提示。
@@ -139,7 +140,7 @@ cmhub 返回结构化 `{error:{code}}`。映射层**按 `code` 优先分支**(
| `app/ai.py` | `gen_title`/`gen_cover` 加 cmhub 分支(请求体+解析+生图下载);抽 backend 选择;错误映射 + 区分重试。`direct` 分支保留现有代码 | M |
| `app/appconfig.py` | `ai` 段加 `backend`/`cmhub` 子段默认值与校验;cmhub Key 的读写与打码(复用脱敏工具);新增 `cmhub_request_url()` 类 helper | S |
| `app/gui/tabs/settings.py` / `app/gui/workers.py` | ⑤ AI 设置按 backend 切换:cmhub 模式显示「网关地址 + API Key + 生文/生图别名 + 测试连接/查余额」;direct 模式保留现有 master-detail;测试连接/查余额走后台 worker。**最大 UI 触点** | M |
| 测试 | `tests/test_ai.py` 增 cmhub mock(titles 列表、image_url 下载、安全下载、各错误码与重试、连接/读超时差异);`test_appconfig` 加 schema 与 `config/cmhub.json` helper;⑤ gui 设置测试跟随 | M |
| 测试 | `tests/test_ai.py` 增 cmhub mock(titles 列表、image_url 下载、安全下载、各错误码与重试、连接/读超时差异);`test_appconfig` 加 schema 与 `data/config/cmhub.json` helper;⑤ gui 设置测试跟随 | M |
| 文档 | `docs/04-architecture.md` §5.1b/§6.2、`docs/api.md`、`docs/03-tech-stack.md`、`current-state.md` 同步 | S |
**明确不动(T-526)**:`editor.py`/`cdp.py`/`chrome.py`/`accounts.py`/`excel.py`/`db.py`,以及 ①采集/③更新/④账号全流程;`generate_batch` 主编排、图片本地路径方案和 T-520 封面开关保持原语义。T-527/T-528 可按任务边界修改 `app/gui/tabs/settings.py`、`app/gui/tabs/generate.py`、`app/gui/workers.py` 的设置与用户提示层。