WIP: UI编辑器自动分图层切图标 #304
@@ -0,0 +1,103 @@
|
||||
# Raw GPT Image 2 图片编辑代理
|
||||
|
||||
更新时间:`2026-09-07`
|
||||
|
||||
## 目标
|
||||
|
||||
提供一个由主站客户端调用的独立同步图片编辑代理:
|
||||
|
||||
```text
|
||||
POST /api/raw/v1/images/edit
|
||||
```
|
||||
|
||||
该入口使用登录态 Bearer access token,不进入 External v1 / MCP OpenAPI,不读取或写入画布、项目资源、素材库、OSS 结果或 `external_generation_job`。
|
||||
|
||||
## 请求合同
|
||||
|
||||
请求使用 `application/json`。图片字段只使用原始图片的 base64 数据和 MIME 类型,不接受 object key、URL、Data URL 或 Blob URL。
|
||||
|
||||
```json
|
||||
{
|
||||
"images": [
|
||||
{
|
||||
"data": "<base64>",
|
||||
"mimeType": "image/png"
|
||||
}
|
||||
],
|
||||
"mask": {
|
||||
"data": "<base64>",
|
||||
"mimeType": "image/png"
|
||||
},
|
||||
"prompt": "修改图片",
|
||||
"quality": "auto",
|
||||
"background": "auto",
|
||||
"output_format": "png",
|
||||
"width": 1536,
|
||||
"height": 1024
|
||||
}
|
||||
```
|
||||
|
||||
`images` 是必填数组,数组成员结构固定为 `{ data, mimeType }`;`mask` 可选并使用相同结构。输入格式由成员的 MIME 类型和解码后的图片字节共同确定,服务端不把输入格式另建成请求参数。`prompt` 必填。`quality`、`background` 和 `output_format` 采用 GPT Image 模型支持的值。`width`、`height` 为整数,组成发送给 provider 的输出尺寸;不把尺寸改写成业务字符串字段。
|
||||
|
||||
服务端发送给 `platform-image` 时固定注入:
|
||||
|
||||
```text
|
||||
model = gpt-image-2
|
||||
n = 1
|
||||
```
|
||||
|
||||
请求不暴露 `model`、`n`、`response_format`、`style`、`user` 或 `output_compression`。
|
||||
|
||||
## 成功响应合同
|
||||
|
||||
响应始终为 JSON,响应只保留 `data` 字段,图片内容只以 base64 返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"b64_json": "<base64>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`data` 保持数组形状,即使服务端固定 `n=1`。响应不重复返回请求参数,不返回 URL、资源 ID、任务 ID、provider 原始 JSON 或 editor 字段。
|
||||
|
||||
## 预检查与计费事务
|
||||
|
||||
所有请求、JSON、base64、图片结构和 provider 参数检查必须在扣费前完成。预检查失败直接返回 4xx,不产生钱包流水,也不调用 provider。
|
||||
|
||||
检查通过后,api-server 调用一个 raw 图片操作的 SpacetimeDB 事务 procedure,在同一事务内完成:
|
||||
|
||||
1. 以认证后的用户和请求 ID 建立 raw 操作幂等事实;
|
||||
2. 按现有图片编辑算法解析价格:GPT Image 2 长边不超过 1536 使用 1K 价格,否则使用 2K 价格;当前默认价格为 3 / 5 泥点;
|
||||
3. 原子扣除用户泥点并写入 `asset_operation_consume` 流水;
|
||||
4. 持久化操作状态,供 provider 返回后成功或失败收口。
|
||||
|
||||
provider 调用在 SpacetimeDB 事务之外执行。成功后调用同一 raw 操作的完成 procedure;失败后调用失败 procedure,由数据库事务写入退款 outbox / settlement 事实。进程崩溃时不依赖 Rust future `Drop` 才能发现需要退款;恢复处理根据持久化的 raw 操作状态完成退款。
|
||||
|
||||
raw 操作使用独立的 operation / ledger 命名空间,例如 `raw-image-edit`,不能复用编辑器资源 ID、编辑器任务 ID 或 `external_generation_job`。
|
||||
|
||||
## Provider 边界
|
||||
|
||||
`platform-image` 保留 VectorEngine 协议细节。raw handler 只负责:认证、JSON DTO、base64 解码、预检查、计费编排和响应映射。provider 请求仍由 `platform-image` 统一构造,并携带 `model`、`n`、`quality`、`background`、`output_format`、尺寸及图片参考字节。
|
||||
|
||||
provider 返回的原始 `size` 必须沿 `GeneratedImages` 结果传回 api-server;raw handler 从该字段解析响应尺寸,再编码 `data[].b64_json`。
|
||||
|
||||
## 代码拆分
|
||||
|
||||
- `server-rs/crates/api-server/src/raw_image.rs`:独立路由 handler、请求/响应 DTO、base64 输入校验、预检查和 raw billing 编排。
|
||||
- `server-rs/crates/platform-image/src/vector_engine/raw_edit.rs`:raw 编辑选项、provider 请求映射和原始响应解码;现有编辑器调用通过默认选项复用,不在业务 handler 复制 provider 协议。
|
||||
- `server-rs/crates/api-server/src/modules/raw.rs`:只注册 `/api/raw/v1/images/edit` 并挂载 Bearer middleware。
|
||||
|
||||
不修改 External v1 OpenAPI;不在 `external_editor_api.rs`、编辑器项目模块或外部生成 worker 中增加 raw 分支。
|
||||
|
||||
## 验收
|
||||
|
||||
- 未认证请求被 Bearer middleware 拒绝。
|
||||
- 预检查失败时钱包无扣费、provider 无请求。
|
||||
- 成功响应严格只包含 `data[].b64_json`。
|
||||
- provider 失败时 raw 操作失败事务产生可恢复退款事实。
|
||||
- raw 请求不创建 `external_generation_job`,不写 editor project/resource/asset/OSS。
|
||||
- 运行 api-server 与 platform-image 定向测试、`npm run check:encoding` 和 `git diff --check`。
|
||||
Reference in New Issue
Block a user