diff --git a/docs/tasks/T-677.md b/docs/tasks/T-677.md index 23b9180..e80f14f 100644 --- a/docs/tasks/T-677.md +++ b/docs/tasks/T-677.md @@ -64,16 +64,25 @@ T-529 把普通用户的 AI 后端收口为 cmhub:⑤ 隐藏「AI 后端」下 ### 4. 必须同版本处理的六个联动 -1. **⑥商品套图入口拦截**:`ai.backend != "cmhub"` 时,正式可见的 `ProductSuiteTab`「生成套图」、图片重试和「AI帮写」入口置灰并说明「商品套图仅支持默认网关」;保存来源切换后立即刷新,切入⑥时也再次刷新。旧 `ImageStudioTab` 即使不在主 Tab 栏,也不得绕过该限制。 -2. **⑥防御性服务拦截**:UI 置灰不足以作为费用边界。`ProductSuiteGenerateWorker` 必须在创建 job 前拒绝非默认网关;`image_studio_generation.run_jobs()` 也要在实际取默认网关 runtime 前拒绝非默认网关,确保内部调用、迟到回调或未来入口不能用默认网关 Key 提交任务。`ProductSuiteAiWriteWorker` 与 `analyze_product_images()` 保持非默认网关不可用;UI 必须在读取默认网关模型目录、展示扣点确认、提交图片理解前拦截,而不是等待运行后报错。 +1. **⑥商品套图入口拦截**:`ai.backend != "cmhub"` 时,正式可见的 `ProductSuiteTab`「生成套图」、图片重试和「AI帮写」入口置灰并说明「商品套图仅支持默认网关」;保存来源切换后立即刷新,切入⑥时也再次刷新。旧 `ImageStudioTab` 不在主 Tab 栏(`app/gui/widgets.py:57` 的 `TAB_TITLES` 不含它,`tests/test_gui.py` 显式断言其不存在),由第 2 条的服务层防线覆盖即可,**不单独为它改 UI**。 +2. **⑥防御性服务拦截,但必须区分"新建"与"取回"**:UI 置灰不足以作为费用边界,同时**不得把已经扣过点的任务困死**。 + + - **拒绝**:新建与新提交——`ProductSuiteGenerateWorker` 在创建 job 前拒绝非默认网关;`image_studio_generation` 侧拦在 `create_generation_jobs()` 与 `_submit_or_resume_job()` 中"尚无 `image_task_id`"的提交分支。 + - **放行**:已提交任务的轮询、下载与保存——`resume_image_jobs()` 同样走 `run_jobs()`(`app/image_studio_generation.py:142-163`),**不能在 `run_jobs()` 入口一刀切拒绝**,否则用户切到自定义网关后,此前已提交到默认网关、已预扣点数、正等待轮询取回的生图任务将永久拿不回来(钱已花、图丢失)。已有 `image_task_id` 的 job 必须继续用默认网关凭据完成轮询与下载。 + - 口径依据:Obsidian《卡密设备绑定与套餐授权方案》第五节 §5「已被服务端接受的异步任务轮询、下载:允许,避免已预扣点数却拿不到结果」。本任务与该原则保持一致,实现时不要另立边界。 + - `ProductSuiteAiWriteWorker` 与 `analyze_product_images()` 保持非默认网关不可用(图片理解无异步任务、不存在已扣点待取回的情形,可直接拒绝);UI 必须在读取默认网关模型目录、展示扣点确认、提交图片理解前拦截,而不是等待运行后报错。 3. **⑥商品套图说明**:⑤自定义面板增加说明行,明确「图片理解与商品套图仅默认网关支持」;拦截提示使用同一中文口径,不显示技术实现或 cmhub Key 信息。 4. **②自定义网关预检**:允许保存不完整配置,但点击②开始生成时、创建 `GenerateWorker` 前按本轮“只生成标题 / 只生成封面 / 生成图文”检查所需 direct 模型是否已启用、类别匹配、模型地址、模型 ID、API Key、接口类型齐全。失败时中文提示去⑤补齐,且不创建 worker、不发请求、不逐条改任务状态。不要等 `_role_model()` 在批量运行中逐条失败。 5. **「批量生成前检查余额」**(`cmhub_check_balance_checkbox`):自定义网关下隐藏——点数余额是默认网关概念。 6. **点数展示文案**:②自定义网关每轮开始时在运行日志和状态栏各明确一次显示「自定义网关(不计点数,费用由服务商收取)」,并清空/隐藏上轮默认网关余额;不得显示 `0 点`、空白余额或沿用旧余额。默认网关下 `points_cost` / `points_balance` 展示保持不变。 -### 5. ⑤ 面板内文案收敛 +### 5. 用户可见文案收敛 -⑤ 面板内以及⑤触发的状态栏用户可见文案中的 `cmhub` 字样收敛为「默认网关」口径,包括分区标题、Base URL/API Key placeholder 与帮助、刷新/测试按钮、连接中/成功/失败结果、明文保存警告(`PLAINTEXT_CMHUB_API_KEY_WARNING`,`app/gui/tabs/settings.py:17`)。内部类名、`objectName`、配置键、日志字段和 `app/ai.py` 的中文错误消息(如"连接 cmhub 超时")不改。 +⑤ 面板内以及⑤触发的状态栏用户可见文案中的 `cmhub` 字样收敛为「默认网关」口径,包括分区标题、Base URL/API Key placeholder 与帮助、刷新/测试按钮、连接中/成功/失败结果、明文保存警告(`PLAINTEXT_CMHUB_API_KEY_WARNING`,`app/gui/tabs/settings.py:17`)。 + +**②的余额展示一并纳入**:`cmhub_balance_label`(`app/gui/tabs/generate.py:1092`,默认文案「cmhub余额:未获取」)虽不在⑤内,但与⑤同屏出现在用户视野中。若只改⑤,会出现⑤显示「默认网关」而②显示「cmhub余额」的两套叫法,用户第一眼即困惑。该 label 的可见文案改为「默认网关余额」口径,与第 4 节第 6 条的自定义网关文案配套。 + +内部类名、`objectName`(含 `cmhub_balance_label` 本身的标识)、配置键、日志字段和 `app/ai.py` 的中文错误消息(如"连接 cmhub 超时")不改。 ### 6. 效果图 @@ -86,13 +95,14 @@ T-529 把普通用户的 AI 后端收口为 cmhub:⑤ 隐藏「AI 后端」下 - [ ] 选默认网关时只显示默认网关配置(Base URL / API Key / 三个别名 / 连接超时 / 检查余额 / 测试连接·查余额);选自定义网关时只显示自定义模型列表、模型详情与默认文本/图像模型选择。 - [ ] 保存后 `config.json` 的 `ai.backend` 正确写入 `cmhub` / `direct`;`cmhub.json` 与 `ai_models.json` 在来回切换保存后内容均不丢失。 - [ ] 载入 `backend=direct` 的存量配置时选中「自定义网关」并正确回填自定义模型;缺失或 `cmhub` 时选中「默认网关」。 -- [ ] 自定义网关下②生文、②生图可用;⑥商品套图的生成、重试和 AI 帮写入口被拦截并提示仅默认网关支持,旧 `ImageStudioTab` 也不能绕过;worker/service 防线证明非默认网关不会创建默认网关 job、读取默认网关模型目录、提交请求或扣点。 +- [ ] 自定义网关下②生文、②生图可用;⑥商品套图的生成、重试和 AI 帮写入口被拦截并提示仅默认网关支持;worker/service 防线证明非默认网关不会创建 job、读取默认网关模型目录、提交新请求或扣点。 +- [ ] **切到自定义网关后,此前已提交(已有 `image_task_id`)的默认网关生图任务仍可通过 `resume_image_jobs()` 完成轮询、下载与保存,不因来源切换被拒绝或丢失**;未提交的 job 则被拒绝创建。 - [ ] ②/⑥运行开始后保存来源切换,不影响已启动任务的来源快照;保存完成后⑥按钮状态立即刷新,重新进入⑥时也正确刷新。 - [ ] 自定义网关下「批量生成前检查余额」不可见;②日志/状态栏显示"不计点数"口径而非 `0 点`,且清除旧余额;默认网关下点数与余额展示不回归。 - [ ] 自定义配置不完整时可保存;②按本轮生成内容在创建 worker 前给出"去⑤补齐"的可读提示,不发请求、不改任务状态、不崩溃。 - [ ] 自定义模型 CRUD 的立即保存与来源选择的待保存语义均有明确中文反馈;放弃设置不回滚已保存模型,但恢复未保存来源选择。 -- [ ] `auto` 接口类型的实际请求行为有测试覆盖,不宣称自动探测或未实现的 `images/generations` 支持。 -- [ ] ⑤ 面板及⑤触发的状态栏可见文案不再出现 `cmhub` 字样;内部标识和 `app/ai.py` 错误消息不在本次范围。 +- [ ] `auto` 接口类型的实际请求行为有测试覆盖,不宣称自动探测或未实现的 `images/generations` 支持(若 `tests/test_ai.py` 现有用例已覆盖该分支,确认后即可,不必重复补)。 +- [ ] ⑤ 面板、⑤触发的状态栏、以及②余额 label 的可见文案不再出现 `cmhub` 字样;内部标识(含 `objectName`、配置键、日志字段)和 `app/ai.py` 错误消息不在本次范围。 - [ ] `tests/test_gui.py` 覆盖:选择器互斥与默认选中、面板显隐、dirty 与保存生效、存量 `backend=direct` 载入、模型立即保存与来源待保存语义、②预检、⑥入口/worker拦截、余额控件显隐、点数文案分支、运行配置快照;`tests/test_ai.py` 覆盖 direct 文本/图片、`auto` 的既有请求路径与缺配置报错;现有 backend 相关断言同步更新不回归。 - [ ] `docs/ui/tab5-settings-T677.svg` 已产出并在 `docs/ui/README.md` 登记。