Files
cmshoppe/docs/tasks/T-679a.md
T
chengmaandClaude Fable 5 34c7a2e148 docs(tasks): close review gaps in custom gateway suite split
对 T-678 细化与 T-679a/b/c 拆分的全栈复核结果:

T-678:修正背景中不准确的收敛理由。api_type 在 app/ai.py 只有 :348、
:350 两处使用且都在图片路径内,文字路径从不读取该字段;不能全局收敛
的真实原因是 appconfig.py:881 对所有模型统一校验,收窄取值集合会让
存量文字模型在载入与保存时抛 ConfigError。方案首条同步改为按校验口径
表述,避免实现时去找不存在的文字侧分支。

T-679a/b/c:三处补加发布门禁,说明三者未全部完成前不得发布。拆分只为
控制改动面,不构成可独立发布的中间态——重复计费的二次确认定义在
T-679c,若 a/b 先上线,用户已能创建并失败 direct 任务却在无提示情况下
重试,属资金口径缺口而非体验缺陷。

T-679a:补记本任务组有意放宽 T-677「不给商品套图新增自定义网关路径」
的边界及理由(套图是来源切换后唯一完全断链的模块,图片理解不在放宽
范围内),避免后续回看误判两者矛盾。

T-679a:比例近似映射改为同时记录用户选择的比例与实际输出尺寸。原方案
只存原始比例会让 DB 记 9:16 而文件实际为 1024x1536;当前 add_asset 的
aspect_ratio 只写入无消费者(app/image_studio.py:707-731)故暂不可见,
但历史展示或导出一旦信任该字段即出错。新增字段迁移须附加式且幂等。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 17:30:08 +08:00

6.5 KiB
Raw Blame History

id, title, phase, deps, status, created
id title phase deps status created
T-679a 商品套图自定义网关多来源任务状态机 7
T-678
TODO 2026-07-20

T-679a 商品套图自定义网关多来源任务状态机

问题 / 背景

本任务组有意放宽 T-677 的既定边界。 T-677 明确写了「不给商品套图和图片理解新增自定义网关路径,本任务只做入口拦截与提示」。放宽的理由是:来源切换后,商品套图是唯一完全断链的模块——②生文生图在自定义网关下可用,只有⑥不可用,用户切走后套图功能整体消失。图片理解(AI 帮写)不在放宽范围内,继续保持默认网关独占。记录这一点是为了避免后续回看时误判 T-677 与本任务组互相矛盾。

发布门禁:T-679a、T-679b、T-679c 未全部完成前不得发布。 三者拆分只为控制单次改动面,不构成可独立发布的中间态。重复计费的二次确认提示定义在 T-679c,若 T-679a/T-679b 先上线,用户已能创建并失败 direct 任务,却会在没有"可能重复收费"提示的情况下重试——这是资金口径缺口,不是体验缺陷。

app/image_studio_generation.py 当前把运行时、提交、轮询和 job 来源硬编码为 cmhub。自定义网关是无 task ID 的同步图片编辑请求,不能复用 cmhub 的异步恢复模型;若只在现有分支上打补丁,停止、超时或程序中断时会出现已扣费图片丢失、误轮询或重复生成。

方案

1. 来源与运行快照

  • 按 worker 启动时冻结的配置解析来源,不能读取运行中被⑤保存的新配置。
  • 固定持久化语义:默认网关为 generation_source="cmhub"、provider="cmhub";自定义网关为 generation_source="direct"、provider="openai_images_edits"。不得把用户填写的 URL、模型名或密钥写入来源字段、SQLite、日志或 UI。
  • 自定义网关 job 的 task_id 必须为空;默认网关 job 的 task ID 只能由 cmhub 提交返回后写入。

2. 同步直连执行

  • 复用 T-678 的有序多图图片编辑请求;每个 job 固定 n=1,直接取得图片字节后保存资产,不调用 _poll_job()。
  • 默认网关路径的提交、轮询、下载和幂等键保持不变。分派必须按 job 的持久化来源而非当前设置判断,避免混合项目误走错误通道。
  • 直连结果资产可不填 remote_url;不得为了填该字段额外拼接、记录或暴露上游地址。
  • 将 MAX_CMHUB_IMAGE_STUDIO_WORKERS 改名为来源中立的并发常量,数值仍为 5;默认和直连共用全局上限,防止一次生成压垮本机或上游。

3. 停止、失败与不确定计费

  • 停止只取消尚未发起的 job。已发出的同步请求不可强杀;如果已收到图片字节,必须先保存资产并标成功,停止只阻止后续 job。
  • 直连请求提交后发生读超时、连接中断或进程退出时,客户端无法确认服务商是否已受理或计费:不自动重试,不自动恢复,不把该 job 放入“继续查询”。标失败并提供后续手动“重新生成”入口。
  • 程序启动或进入项目时,遗留 running 的 direct job 统一标为失败,中文原因说明“程序中断,无法确认生成结果,请手动重新生成”;不得自动补发。
  • 直连超时取冻结模型的 connect_timeout_seconds 和 timeout_seconds;若后者未设置,使用项目已有的受限默认值。不得使用 cmhub submit/poll/read timeout 常量。

4. 比例与参考图

  • 套图比例固定映射:1:1 -> 1024x1024;3:4、9:16 -> 1024x1536;4:3、16:9 -> 1536x1024。映射覆盖 product_suite.RATIOS 的全部五个取值;后四种为近似映射。
  • 资产必须同时记录用户选择的比例与实际输出尺寸。 只保存原始比例会让 DB 记着 9:16 而文件实际是 1024×1536(2:3)。当前 image_studio.add_asset() 的 aspect_ratio 只写入、无下游消费者(app/image_studio.py:707-731),所以暂不产生可见故障;但一旦历史展示、导出或后续上传开始信任该字段就会出错。补充实际尺寸字段属于本任务范围,不留给以后修。
  • 任务层向调用方返回“是否近似比例”的结构化结果,T-679b 负责在确认框中告知用户;不得静默伪造精确比例。
  • 首图主体与其余参考图的规则必须使用已冻结、已持久化的 job prompt;不能在 HTTP 调用层临时拼接,避免确认预览、历史 prompt 与实际请求不一致。

验收要点

  • 可创建并执行 direct job,字段值精确为 direct / openai_images_edits / 空 task_id。
  • direct 请求不调用 cmhub 提交、轮询、余额、价格或下载路径;cmhub job 行为不变。
  • 已返回字节的 direct job 即使用户点击停止也会保存成功;未开始 job 才会取消。
  • direct 不发生自动重试;遗留 running direct job 不会自动重发或进入继续查询。
  • 比例映射、近似标记、n=1、多图顺序和 prompt 一致性有纯逻辑测试。
  • 生成资产同时记录用户选择的比例与实际输出尺寸;新增字段的迁移为附加式且幂等,存量资产缺该字段时不报错、不阻塞历史展示。
  • 直连模型 URL、密钥与原始响应不进入 SQLite、事件日志或异常面向用户的文案。

测试与文档

  • tests/test_image_studio_generation.py:来源分派、状态转移、停止边界、超时、遗留运行任务、比例映射、混合 job 防串路与无自动重试。
  • tests/test_image_studio.py:来源字段和中断恢复的数据访问。
  • 更新 docs/04-architecture.md、docs/api.md:记录两种来源 job 生命周期。

验证

py -3.10 -m unittest tests.test_image_studio_generation tests.test_image_studio tests.test_ai
py -3.10 -m ruff check app tests main.py
py -3.10 -m compileall app main.py
git diff --check

边界(不改什么)

  • 不修改⑥按钮可用性、确认框、价格展示、历史 UI;见 T-679b/T-679c。
  • 不改 cmhub 协议、幂等键和点数账本;不新增自动重试、provider 私有适配或接口探测。
  • 不改图片理解、Chrome/CDP、Excel 或蝦皮更新流程。

关联

  • T-678:直连图片编辑请求和多图契约。
  • T-679b:消费本任务返回的来源、比例与停止语义。
  • T-679c:消费本任务的中断状态与重试语义。

执行记录

(做完在这里写:变更文件、状态机决策、验证命令及结果。)