fix(media): 对齐 EasyAI 媒体响应与转存策略

统一媒体异步提交和轮询响应,扩展 /ai/result 到当前用户的 Gateway 媒体任务,并保持既有 Gateway 字段兼容。\n\n启用转存但无可用渠道时回退到 24 小时本地静态资源;关闭转存时保留图片、音频等上游 Base64 字段。同步更新文件上传兼容结构、OpenAPI、管理端说明和回归测试。\n\n验证:cd apps/api && env -u AI_GATEWAY_TEST_DATABASE_URL go test ./... -count=1;gofmt -l 无输出;pnpm nx run web:typecheck。
This commit is contained in:
2026-07-23 22:35:41 +08:00
parent 8b7d3e9c9a
commit 76a7702925
15 changed files with 1562 additions and 163 deletions
+200 -37
View File
@@ -346,6 +346,103 @@ definitions:
$ref: '#/definitions/store.DailyTokenUsage'
type: array
type: object
httpapi.EasyAIGeneratedResponse:
properties:
cancellable:
type: boolean
code:
type: string
created:
example: 1784772000000
type: integer
data:
items:
$ref: '#/definitions/httpapi.EasyAIMediaOutput'
type: array
message:
type: string
output:
items:
type: string
type: array
output_content:
items:
$ref: '#/definitions/httpapi.EasyAIMediaOutput'
type: array
query_url:
example: /api/v1/ai/result/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
result:
additionalProperties: true
type: object
status:
enum:
- submitted
- process
- success
- failed
example: success
type: string
submitted:
type: boolean
task_id:
example: 9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
taskId:
example: 9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
upstream_task_id:
example: provider-task-123
type: string
usage:
additionalProperties: true
type: object
type: object
httpapi.EasyAIMediaOutput:
properties:
audio_url:
type: string
b64_json:
description: B64JSON is retained when result media transfer is disabled.
type: string
content:
type: string
duration:
type: number
format:
type: string
height:
type: integer
image_url:
type: string
metadata:
additionalProperties: true
type: object
mime_type:
type: string
source_resolution:
type: string
target_resolution:
type: string
text:
type: string
type:
enum:
- image
- video
- audio
- file
- text
example: video
type: string
url:
example: https://cdn.example.com/output.mp4
type: string
video_url:
type: string
width:
type: integer
type: object
httpapi.ErrorEnvelope:
properties:
error:
@@ -374,7 +471,7 @@ definitions:
$ref: '#/definitions/store.FileStorageChannel'
type: array
type: object
httpapi.FileUploadResponse:
httpapi.FileUploadData:
properties:
assetStorage:
additionalProperties: true
@@ -395,6 +492,32 @@ definitions:
example: /static/uploaded/upload-abc123.png
type: string
type: object
httpapi.FileUploadResponse:
properties:
assetStorage:
additionalProperties: true
type: object
contentType:
example: image/png
type: string
data:
$ref: '#/definitions/httpapi.FileUploadData'
filename:
example: image.png
type: string
id:
example: file_abc123
type: string
size:
example: 1024
type: integer
status:
example: success
type: string
url:
example: /static/uploaded/upload-abc123.png
type: string
type: object
httpapi.GeminiErrorEnvelope:
properties:
error:
@@ -826,6 +949,26 @@ definitions:
example: invalid_request_error
type: string
type: object
httpapi.OpenAIImageData:
properties:
b64_json:
type: string
revised_prompt:
type: string
url:
example: https://cdn.example.com/output.png
type: string
type: object
httpapi.OpenAIImagesResponse:
properties:
created:
example: 1710000000
type: integer
data:
items:
$ref: '#/definitions/httpapi.OpenAIImageData'
type: array
type: object
httpapi.PlatformListResponse:
properties:
items:
@@ -1092,8 +1235,17 @@ definitions:
properties:
next:
$ref: '#/definitions/httpapi.TaskNextLinks'
query_url:
example: /api/v1/ai/result/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
status:
example: submitted
type: string
task:
$ref: '#/definitions/store.GatewayTask'
task_id:
example: 9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
taskId:
example: 9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
@@ -1140,6 +1292,9 @@ definitions:
events:
example: /api/v1/tasks/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25/events
type: string
result:
example: /api/v1/ai/result/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25
type: string
type: object
httpapi.TaskParamPreprocessingLogListResponse:
properties:
@@ -6638,6 +6793,7 @@ paths:
- playground
/api/v1/ai/result/{taskID}:
get:
description: 查询当前用户的图片、视频、音频、视频高清和矢量化任务,并返回 EasyAI GeneratedResponse 兼容结构。
parameters:
- description: 任务 ID
in: path
@@ -6650,13 +6806,16 @@ paths:
"200":
description: OK
schema:
additionalProperties: true
type: object
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
security:
- BearerAuth: []
summary: 查询 server-main 兼容视频结果
summary: 查询 server-main EasyAIClient 兼容任务结果
tags:
- volces-compatible
- tasks
/api/v1/api-keys:
get:
description: 返回当前用户创建的 API Key 元数据,secret 只在创建时返回。
@@ -7451,7 +7610,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.OpenAIImagesResponse'
"202":
description: Accepted
schema:
@@ -7499,7 +7658,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.OpenAIImagesResponse'
"202":
description: Accepted
schema:
@@ -7548,7 +7707,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -7926,7 +8085,8 @@ paths:
post:
consumes:
- application/json
description: 统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。
description: 默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway
与 server-main EasyAIClient 的异步提交结构。
parameters:
- description: true 时异步创建任务并返回 202
in: header
@@ -7936,7 +8096,7 @@ paths:
in: header
name: Idempotency-Key
type: string
- description: AI 任务请求,字段随任务类型变化
- description: 媒体任务请求,字段随任务类型变化
in: body
name: input
required: true
@@ -7948,7 +8108,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -7983,9 +8143,9 @@ paths:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 创建或执行 AI 任务
summary: 创建 EasyAI 媒体任务
tags:
- tasks
- media
/api/v1/openapi.json:
get:
description: 返回当前构建内嵌的完整机器可读 Swagger JSON,供 Agent 在 SKILL references 未覆盖接口时查询。
@@ -8470,7 +8630,8 @@ paths:
post:
consumes:
- application/json
description: 统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。
description: 默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway
与 server-main EasyAIClient 的异步提交结构。
parameters:
- description: true 时异步创建任务并返回 202
in: header
@@ -8480,7 +8641,7 @@ paths:
in: header
name: Idempotency-Key
type: string
- description: AI 任务请求,字段随任务类型变化
- description: 媒体任务请求,字段随任务类型变化
in: body
name: input
required: true
@@ -8492,7 +8653,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -8527,14 +8688,15 @@ paths:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 创建或执行 AI 任务
summary: 创建 EasyAI 媒体任务
tags:
- tasks
- media
/api/v1/speech/generations:
post:
consumes:
- application/json
description: 统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。
description: 默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway
与 server-main EasyAIClient 的异步提交结构。
parameters:
- description: true 时异步创建任务并返回 202
in: header
@@ -8544,7 +8706,7 @@ paths:
in: header
name: Idempotency-Key
type: string
- description: AI 任务请求,字段随任务类型变化
- description: 媒体任务请求,字段随任务类型变化
in: body
name: input
required: true
@@ -8556,7 +8718,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -8591,9 +8753,9 @@ paths:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 创建或执行 AI 任务
summary: 创建 EasyAI 媒体任务
tags:
- tasks
- media
/api/v1/tasks:
get:
description: 按当前用户列出任务,支持关键字、模型类型、时间范围和分页过滤。
@@ -8803,18 +8965,18 @@ paths:
"200":
description: OK
schema:
additionalProperties: true
type: object
$ref: '#/definitions/httpapi.TaskAcceptedResponse'
security:
- BearerAuth: []
summary: 创建 server-main 兼容视频任务
tags:
- volces-compatible
- media
/api/v1/videos/generations:
post:
consumes:
- application/json
description: 统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。
description: 默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway
与 server-main EasyAIClient 的异步提交结构。
parameters:
- description: true 时异步创建任务并返回 202
in: header
@@ -8824,7 +8986,7 @@ paths:
in: header
name: Idempotency-Key
type: string
- description: AI 任务请求,字段随任务类型变化
- description: 媒体任务请求,字段随任务类型变化
in: body
name: input
required: true
@@ -8836,7 +8998,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -8871,9 +9033,9 @@ paths:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 创建或执行 AI 任务
summary: 创建 EasyAI 媒体任务
tags:
- tasks
- media
/api/v1/videos/omni-video:
post:
consumes:
@@ -8983,7 +9145,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -9017,7 +9179,8 @@ paths:
post:
consumes:
- application/json
description: 统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。
description: 默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway
与 server-main EasyAIClient 的异步提交结构。
parameters:
- description: true 时异步创建任务并返回 202
in: header
@@ -9027,7 +9190,7 @@ paths:
in: header
name: Idempotency-Key
type: string
- description: AI 任务请求,字段随任务类型变化
- description: 媒体任务请求,字段随任务类型变化
in: body
name: input
required: true
@@ -9039,7 +9202,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/httpapi.CompatibleResponse'
$ref: '#/definitions/httpapi.EasyAIGeneratedResponse'
"202":
description: Accepted
schema:
@@ -9074,9 +9237,9 @@ paths:
$ref: '#/definitions/httpapi.ErrorEnvelope'
security:
- BearerAuth: []
summary: 创建或执行 AI 任务
summary: 创建 EasyAI 媒体任务
tags:
- tasks
- media
/api/v1/voice_clone/voices:
get:
description: 返回当前用户在网关中维护的克隆音色,以及克隆时绑定的平台与平台模型。