fix: 对齐 cmhub 的 images_edits 图片编辑协议并启用路由 #60

Closed
opened 2026-08-25 16:12:24 +08:00 by ila · 5 comments
Owner

基本信息

  • 类型:缺陷修复与本机 Provider 配置
  • 所属 Epic:#3
  • 所属 MVP / 版本:#35 / MVP-2
  • 关联工单:#54、#58
  • 阶段:已完成

原始需求

  • 来源:用户对话
  • 提出时间:2026-08-25
  • 用户目的(脱敏摘要):同一 Provider 和模型在 cmhub 通过图片编辑接口多数可在 150 秒内完成;要求 Chorus 按已确认建议对齐并修复。

已确认事实

  • cmhub 的模型为 api_type=auto,其 URL 路径包含 /v1/images/edits,运行时解析为 images_edits。
  • cmhub 使用 multipart POST /v1/images/edits,文件字段为重复的 image,并提交 model/prompt/n/size。
  • Chorus 当前真实失败任务使用 /v1/images/generations JSON 文生图;generation #9 在上游阶段等待约 300 秒后超时。
  • Chorus 已有图片编辑 UI、上传校验、images_edits Provider、image_edit 路由和 mock 集成链路,无需新增页面或改变主要交互。

目标

  1. 将 Chorus 的 OpenAI-compatible images_edits multipart 请求对齐到已验证的 cmhub 形态。
  2. 在本机配置独立的 gpt-image-2 / images_edits / image_edit ProviderModel、模板和活动路由。
  3. 停用当前 Provider 上不稳定的 image_generate 活动路由,避免继续误导用户提交文生图。
  4. 自动测试通过后只执行一次低风险、合成输入图片的真实图片编辑验证。

非目标

  • 不新增或重构用户端页面。
  • 不把完整 /images/edits 写作 Provider base_url;Chorus base_url 保持到 /v1 并由适配器拼接端点。
  • 不修改 SSRF、retryable 判定、限流、数据库结构或超时上限。
  • 不增加重试,不反复使用真实上游额度。
  • 不声明该 Provider 支持稳定文生图;未来恢复 image_generate 需独立验证。

实施方案

  • images_edits multipart 文件字段由 image[] 改为重复的 image。
  • 请求固定写入 n=1;模型 extra_body 配置 size=1024x1024。
  • 更新 mock Provider 和协议测试,断言端点、字段名、n、size、原图与响应解析。
  • 复用现有 Portal 图片编辑交互、上传边界、Prompt 模板和路由机制。
  • 本机通过管理 API 配置,不在 Git、工单、Wiki、日志或命令输出记录真实 Provider 地址、Key、图片或响应正文。

风险与回退

  • multipart 字段变化可能影响只接受 image[] 的其他兼容 Provider;当前范围以已经验证成功的目标 Provider 协议为准,并以 mock 回归固定契约。
  • 真实验证可能产生一次上游费用。
  • 回退:恢复 multipart 字段和固定字段代码;停用新增 image_edit 路由并恢复原活动路由状态,不删除 generation/attempt 审计。

验收标准

  • images_edits 请求使用 POST /v1/images/edits、重复 image 文件字段以及 model/prompt/n=1/size。
  • 单元测试、Provider mock、受影响 Go 测试通过。
  • 本机存在启用的 images_edits/image_edit 模型、模板、路由池和活动路由;目标 Provider 的不稳定 image_generate 活动路由已停用。
  • Portal 图片编辑可上传一张合成主体图并形成可审计终态;真实上游最多调用一次。
  • 不泄露凭据、Provider 主机、Prompt、图片、用户数据或响应正文。

设计证据

复用已验收的 Portal 图片编辑页面、上传状态和交互,以及既有 images_edits 技术设计与 mock 集成证据;本次不改变页面结构、流程、权限或异常交互,因此不新增 UI 原型。

文档影响

若 multipart 字段契约发生长期变化,更新 Gitea Wiki 的架构/业务规则对应页面并同步核心 docs/ 镜像;本机 Provider 配置值和真实验证结果仅进入任务归档。

需求变更(2026-08-25)

  • 原因:停用不稳定的 image_generate 路由后,Portal 仍默认允许文生图,提交时才返回 generation route is unavailable,用户体验不合理。
  • 用户确认:按照建议继续修复。
  • 新增范围:Portal 页面按活动且启用的路由提供能力状态;仅 image_edit 可用时默认选择图片编辑,并禁用文生图入口;路由状态变化后刷新页面即可生效。
  • 不变范围:不恢复不稳定的文生图路由,不修改 Provider、SSRF、retryable、限流、数据库或主要图片编辑流程。
  • 设计证据:复用已验收的双模式工作区,仅增加既有模式按钮的 disabled/默认选中状态和不可用提示;属于现有界面的小范围状态修复,不新增页面或主要交互,不另建原型。
  • 新增验收:无 image_generate 活动可用路由时不能提交文生图;存在 image_edit 路由时页面默认进入图片编辑且仍可上传提交;两者均不可用时生成按钮不可提交并显示明确状态。

需求变更(2026-08-25,恢复文生图)

  • 用户确认:接受旧 image_generate 路由可能再次发生约 300 秒超时的风险,要求恢复 Portal 的“文生图”选择。
  • 实施范围:重新启用现有 RoutePool #2;刷新页面后 image_generate 应可选择,image_edit 继续可用。
  • 非目标:不修改协议适配、超时、retryable、模型或 Provider 配置,不执行真实文生图验证。
  • 回退:再次停用 RoutePool #2;Portal 将按现有路由感知逻辑自动禁用文生图。
  • 验收:管理端路由池启用且活动绑定/成员可用;Portal 返回两种图片能力均可用;不消耗真实上游额度。
## 基本信息 - 类型:缺陷修复与本机 Provider 配置 - 所属 Epic:#3 - 所属 MVP / 版本:#35 / MVP-2 - 关联工单:#54、#58 - 阶段:已完成 ## 原始需求 - 来源:用户对话 - 提出时间:2026-08-25 - 用户目的(脱敏摘要):同一 Provider 和模型在 cmhub 通过图片编辑接口多数可在 150 秒内完成;要求 Chorus 按已确认建议对齐并修复。 ## 已确认事实 - cmhub 的模型为 `api_type=auto`,其 URL 路径包含 `/v1/images/edits`,运行时解析为 `images_edits`。 - cmhub 使用 multipart `POST /v1/images/edits`,文件字段为重复的 `image`,并提交 `model/prompt/n/size`。 - Chorus 当前真实失败任务使用 `/v1/images/generations` JSON 文生图;generation #9 在上游阶段等待约 300 秒后超时。 - Chorus 已有图片编辑 UI、上传校验、`images_edits` Provider、`image_edit` 路由和 mock 集成链路,无需新增页面或改变主要交互。 ## 目标 1. 将 Chorus 的 OpenAI-compatible `images_edits` multipart 请求对齐到已验证的 cmhub 形态。 2. 在本机配置独立的 `gpt-image-2 / images_edits / image_edit` ProviderModel、模板和活动路由。 3. 停用当前 Provider 上不稳定的 `image_generate` 活动路由,避免继续误导用户提交文生图。 4. 自动测试通过后只执行一次低风险、合成输入图片的真实图片编辑验证。 ## 非目标 - 不新增或重构用户端页面。 - 不把完整 `/images/edits` 写作 Provider base_url;Chorus base_url 保持到 `/v1` 并由适配器拼接端点。 - 不修改 SSRF、retryable 判定、限流、数据库结构或超时上限。 - 不增加重试,不反复使用真实上游额度。 - 不声明该 Provider 支持稳定文生图;未来恢复 `image_generate` 需独立验证。 ## 实施方案 - `images_edits` multipart 文件字段由 `image[]` 改为重复的 `image`。 - 请求固定写入 `n=1`;模型 `extra_body` 配置 `size=1024x1024`。 - 更新 mock Provider 和协议测试,断言端点、字段名、`n`、`size`、原图与响应解析。 - 复用现有 Portal 图片编辑交互、上传边界、Prompt 模板和路由机制。 - 本机通过管理 API 配置,不在 Git、工单、Wiki、日志或命令输出记录真实 Provider 地址、Key、图片或响应正文。 ## 风险与回退 - multipart 字段变化可能影响只接受 `image[]` 的其他兼容 Provider;当前范围以已经验证成功的目标 Provider 协议为准,并以 mock 回归固定契约。 - 真实验证可能产生一次上游费用。 - 回退:恢复 multipart 字段和固定字段代码;停用新增 image_edit 路由并恢复原活动路由状态,不删除 generation/attempt 审计。 ## 验收标准 - [x] `images_edits` 请求使用 `POST /v1/images/edits`、重复 `image` 文件字段以及 `model/prompt/n=1/size`。 - [x] 单元测试、Provider mock、受影响 Go 测试通过。 - [x] 本机存在启用的 `images_edits/image_edit` 模型、模板、路由池和活动路由;目标 Provider 的不稳定 `image_generate` 活动路由已停用。 - [x] Portal 图片编辑可上传一张合成主体图并形成可审计终态;真实上游最多调用一次。 - [x] 不泄露凭据、Provider 主机、Prompt、图片、用户数据或响应正文。 ## 设计证据 复用已验收的 Portal 图片编辑页面、上传状态和交互,以及既有 `images_edits` 技术设计与 mock 集成证据;本次不改变页面结构、流程、权限或异常交互,因此不新增 UI 原型。 ## 文档影响 若 multipart 字段契约发生长期变化,更新 Gitea Wiki 的架构/业务规则对应页面并同步核心 `docs/` 镜像;本机 Provider 配置值和真实验证结果仅进入任务归档。 ## 需求变更(2026-08-25) - 原因:停用不稳定的 `image_generate` 路由后,Portal 仍默认允许文生图,提交时才返回 `generation route is unavailable`,用户体验不合理。 - 用户确认:按照建议继续修复。 - 新增范围:Portal 页面按活动且启用的路由提供能力状态;仅 `image_edit` 可用时默认选择图片编辑,并禁用文生图入口;路由状态变化后刷新页面即可生效。 - 不变范围:不恢复不稳定的文生图路由,不修改 Provider、SSRF、retryable、限流、数据库或主要图片编辑流程。 - 设计证据:复用已验收的双模式工作区,仅增加既有模式按钮的 disabled/默认选中状态和不可用提示;属于现有界面的小范围状态修复,不新增页面或主要交互,不另建原型。 - 新增验收:无 `image_generate` 活动可用路由时不能提交文生图;存在 `image_edit` 路由时页面默认进入图片编辑且仍可上传提交;两者均不可用时生成按钮不可提交并显示明确状态。 ## 需求变更(2026-08-25,恢复文生图) - 用户确认:接受旧 `image_generate` 路由可能再次发生约 300 秒超时的风险,要求恢复 Portal 的“文生图”选择。 - 实施范围:重新启用现有 RoutePool #2;刷新页面后 `image_generate` 应可选择,`image_edit` 继续可用。 - 非目标:不修改协议适配、超时、retryable、模型或 Provider 配置,不执行真实文生图验证。 - 回退:再次停用 RoutePool #2;Portal 将按现有路由感知逻辑自动禁用文生图。 - 验收:管理端路由池启用且活动绑定/成员可用;Portal 返回两种图片能力均可用;不消耗真实上游额度。
Author
Owner

实施与验证结果(2026-08-25)

  • 实现提交:c1b579f(已推送 main)。
  • images_edits multipart 已改为重复 image 文件字段,并固定发送 n=1;size 继续通过白名单 extra_body 发送。
  • Provider mock 与协议测试已同步对齐,并直接解析 multipart 断言端点、model、prompt、n、size、文件字段和响应解析。
  • 本机管理配置已新增 ProviderModel #5(images_edits/image_edit)与活动 RoutePool #3;复用既有图片编辑模板;旧 image_generate RoutePool #2 已停用。未记录 Provider 主机或凭据。
  • Supervisor 已重新构建并重启 chorus-user,Portal 登录页 HTTP 200。
  • 自动验证:go test ./...、go vet ./...、git diff --check、python dev_scripts/harness.py check --strict、43 项 Harness 单测、核心 Wiki sync --check 均通过。
  • 浏览器插件连接不可用,因此未把可视化浏览器回归记为已验证;页面结构和交互未修改。
  • 按工单限制只执行 1 次真实图片编辑:generation #10 使用合成的 2×2 PNG,Provider attempt 约 1077ms 后返回不可重试 upstream_bad_request,无生成输出。已按 400 立即停止,未更换图片或参数再次调用。
  • 脱敏审计无法区分上游拒绝原因;最可能的待核实项是合成图尺寸过小,但这只是推测,不能作为已确认根因。后续如需用正常尺寸合成图再验证,必须另行得到一次真实调用授权。

文档

  • Wiki Architecture-and-Code-Map revision:abccc87d2bd89378cb73e6bfa00e0f8868da672a
  • Wiki Business-Rules-and-Glossary revision:d6a30f04c99acfd17ded626d426323eba86c27ab
  • 核心 docs/ 镜像已同步并纳入提交。
## 实施与验证结果(2026-08-25) - 实现提交:`c1b579f`(已推送 `main`)。 - `images_edits` multipart 已改为重复 `image` 文件字段,并固定发送 `n=1`;`size` 继续通过白名单 `extra_body` 发送。 - Provider mock 与协议测试已同步对齐,并直接解析 multipart 断言端点、model、prompt、n、size、文件字段和响应解析。 - 本机管理配置已新增 ProviderModel #5(`images_edits/image_edit`)与活动 RoutePool #3;复用既有图片编辑模板;旧 `image_generate` RoutePool #2 已停用。未记录 Provider 主机或凭据。 - Supervisor 已重新构建并重启 `chorus-user`,Portal 登录页 HTTP 200。 - 自动验证:`go test ./...`、`go vet ./...`、`git diff --check`、`python dev_scripts/harness.py check --strict`、43 项 Harness 单测、核心 Wiki `sync --check` 均通过。 - 浏览器插件连接不可用,因此未把可视化浏览器回归记为已验证;页面结构和交互未修改。 - 按工单限制只执行 1 次真实图片编辑:generation #10 使用合成的 2×2 PNG,Provider attempt 约 1077ms 后返回不可重试 `upstream_bad_request`,无生成输出。已按 400 立即停止,未更换图片或参数再次调用。 - 脱敏审计无法区分上游拒绝原因;最可能的待核实项是合成图尺寸过小,但这只是推测,不能作为已确认根因。后续如需用正常尺寸合成图再验证,必须另行得到一次真实调用授权。 ## 文档 - Wiki `Architecture-and-Code-Map` revision:`abccc87d2bd89378cb73e6bfa00e0f8868da672a` - Wiki `Business-Rules-and-Glossary` revision:`d6a30f04c99acfd17ded626d426323eba86c27ab` - 核心 `docs/` 镜像已同步并纳入提交。
Author
Owner

归档与一致性

  • Wiki 任务归档:Task-60-对齐-images_edits-图片编辑协议
  • 在线回读 revision:117076f446b0522651474d97a583c5fe8b6f97e5
  • 实现提交:c1b579f,已推送 main
  • python dev_scripts/harness.py sync --check:通过,核心 Wiki 镜像一致
  • 按流程未导出 docs/task/;只有用户明确要求时才导出任务归档
  • 工单保持待验收;generation #10 的上游 400 和未执行第二次真实调用已写入归档
## 归档与一致性 - Wiki 任务归档:`Task-60-对齐-images_edits-图片编辑协议` - 在线回读 revision:`117076f446b0522651474d97a583c5fe8b6f97e5` - 实现提交:`c1b579f`,已推送 `main` - `python dev_scripts/harness.py sync --check`:通过,核心 Wiki 镜像一致 - 按流程未导出 `docs/task/`;只有用户明确要求时才导出任务归档 - 工单保持待验收;generation #10 的上游 400 和未执行第二次真实调用已写入归档
Author
Owner

路由感知修复完成(2026-08-25)

  • 新增提交:9bb713b,已推送 main;此前协议提交 c1b579f 保持不变。
  • Portal 通过活动路由快照判断 image_generate / image_edit 可用性。当前仅图片编辑路由可用时,页面默认图片编辑、禁用文生图并显示说明;两种图片路由都不可用时禁用提交。
  • 保留服务端提交路由校验;页面状态只提供即时反馈。既有文本历史重试仍可走原文本提交入口,不受图片路由按钮禁用影响。
  • 新增服务测试覆盖双路由、仅编辑、无路由和数据库错误;模板测试覆盖 meta、禁用状态、默认模式、状态提示和提交文案。
  • Supervisor 已重新构建并重启 chorus-user;三项服务均为 Running,本机 Portal 登录页绕过环境代理后 HTTP 200,Chrome 可正常打开登录界面。未输入账号进入受保护工作台,因此登录后视觉状态以自动测试和服务端模板渲染为证据;未发起任何新真实生成。
  • 验证通过:pnpm --dir portal/web build、go test ./...、go vet ./...、git diff --check、python dev_scripts/harness.py check --strict、43 项 Harness 单测、python dev_scripts/harness.py sync --check。
  • Wiki:Architecture-and-Code-Map@2fac5b4b6c936d234e63c11ad57aba40777f9d7a;Business-Rules-and-Glossary@8eecc350340b2e27bad9bdf4b365fc3057517ffe。
  • 任务归档:Task-60-对齐-images_edits-图片编辑协议.-,在线 API 回读 revision 0e2308d32d1206941ef4cc4abcadb7ce351d24c1。MCP 对该旧标题存在重复编码,故仅回读步骤回退到 Gitea API。
  • 核心 docs/ 镜像已同步;按流程未导出 docs/task/。

工单现保持“待验收”,不关闭。

## 路由感知修复完成(2026-08-25) - 新增提交:`9bb713b`,已推送 `main`;此前协议提交 `c1b579f` 保持不变。 - Portal 通过活动路由快照判断 `image_generate` / `image_edit` 可用性。当前仅图片编辑路由可用时,页面默认图片编辑、禁用文生图并显示说明;两种图片路由都不可用时禁用提交。 - 保留服务端提交路由校验;页面状态只提供即时反馈。既有文本历史重试仍可走原文本提交入口,不受图片路由按钮禁用影响。 - 新增服务测试覆盖双路由、仅编辑、无路由和数据库错误;模板测试覆盖 meta、禁用状态、默认模式、状态提示和提交文案。 - Supervisor 已重新构建并重启 `chorus-user`;三项服务均为 Running,本机 Portal 登录页绕过环境代理后 HTTP 200,Chrome 可正常打开登录界面。未输入账号进入受保护工作台,因此登录后视觉状态以自动测试和服务端模板渲染为证据;未发起任何新真实生成。 - 验证通过:`pnpm --dir portal/web build`、`go test ./...`、`go vet ./...`、`git diff --check`、`python dev_scripts/harness.py check --strict`、43 项 Harness 单测、`python dev_scripts/harness.py sync --check`。 - Wiki:`Architecture-and-Code-Map@2fac5b4b6c936d234e63c11ad57aba40777f9d7a`;`Business-Rules-and-Glossary@8eecc350340b2e27bad9bdf4b365fc3057517ffe`。 - 任务归档:`Task-60-对齐-images_edits-图片编辑协议.-`,在线 API 回读 revision `0e2308d32d1206941ef4cc4abcadb7ce351d24c1`。MCP 对该旧标题存在重复编码,故仅回读步骤回退到 Gitea API。 - 核心 `docs/` 镜像已同步;按流程未导出 `docs/task/`。 工单现保持“待验收”,不关闭。
Author
Owner

文生图路由已恢复(2026-08-25)

  • 用户已确认接受原 image_generate 路由可能再次出现约 300 秒超时的风险。
  • 通过管理 API 启用 RoutePool #2,保持活动绑定和原成员;版本由 2 更新到 3,管理审计已记录。
  • 重启 chorus-user 后进程为 Running,登录页 HTTP 200。
  • 使用受控测试账户读取工作台:HTTP 200;image_generate=true、image_edit=true;文生图按钮不含禁用状态;默认模式仍为图片编辑。
  • 未发起真实生成请求,不消耗上游额度;未修改代码、Provider、模型、协议、超时或 retryable,因此没有新 Git 提交。
  • 正确任务归档已恢复并更新:Task-60-对齐-images_edits-图片编辑协议.-@d2e1920bad8efa9d1c8312a746455c58cab3363f。
  • Wiki API 回退过程中曾生成一个标题含问号的空白重复页面。正确归档未丢失且已从 revision 恢复;按 Wiki 删除门禁,重复空页暂未删除,等待用户明确授权。

工单恢复为“待验收”,不关闭。

## 文生图路由已恢复(2026-08-25) - 用户已确认接受原 `image_generate` 路由可能再次出现约 300 秒超时的风险。 - 通过管理 API 启用 RoutePool #2,保持活动绑定和原成员;版本由 2 更新到 3,管理审计已记录。 - 重启 `chorus-user` 后进程为 Running,登录页 HTTP 200。 - 使用受控测试账户读取工作台:HTTP 200;`image_generate=true`、`image_edit=true`;文生图按钮不含禁用状态;默认模式仍为图片编辑。 - 未发起真实生成请求,不消耗上游额度;未修改代码、Provider、模型、协议、超时或 retryable,因此没有新 Git 提交。 - 正确任务归档已恢复并更新:`Task-60-对齐-images_edits-图片编辑协议.-@d2e1920bad8efa9d1c8312a746455c58cab3363f`。 - Wiki API 回退过程中曾生成一个标题含问号的空白重复页面。正确归档未丢失且已从 revision 恢复;按 Wiki 删除门禁,重复空页暂未删除,等待用户明确授权。 工单恢复为“待验收”,不关闭。
Author
Owner

用户验收通过

  • 验收时间:2026-08-27 14:57:05 +08:00
  • 验收人:用户
  • 结论:用户明确确认本工单通过验收,接受当前实现、部署与已记录的验证结果。
  • 文档:沿用工单中已经完成的 Wiki/镜像处理;没有新的长期事实变化。
  • 状态:已完成,关闭工单。
## 用户验收通过 - 验收时间:2026-08-27 14:57:05 +08:00 - 验收人:用户 - 结论:用户明确确认本工单通过验收,接受当前实现、部署与已记录的验证结果。 - 文档:沿用工单中已经完成的 Wiki/镜像处理;没有新的长期事实变化。 - 状态:已完成,关闭工单。
ila closed this issue 2026-08-27 14:57:22 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/chorus#60