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
+261 -37
View File
@@ -4709,13 +4709,14 @@
"BearerAuth": []
}
],
"description": "查询当前用户的图片、视频、音频、视频高清和矢量化任务,并返回 EasyAI GeneratedResponse 兼容结构。",
"produces": [
"application/json"
],
"tags": [
"volces-compatible"
"tasks"
],
"summary": "查询 server-main 兼容视频结果",
"summary": "查询 server-main EasyAIClient 兼容任务结果",
"parameters": [
{
"type": "string",
@@ -4729,8 +4730,13 @@
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
}
}
@@ -5976,7 +5982,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.OpenAIImagesResponse"
}
},
"202": {
@@ -6051,7 +6057,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.OpenAIImagesResponse"
}
},
"202": {
@@ -6126,7 +6132,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -6710,7 +6716,7 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"description": "默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway 与 server-main EasyAIClient 的异步提交结构。",
"consumes": [
"application/json"
],
@@ -6718,9 +6724,9 @@
"application/json"
],
"tags": [
"tasks"
"media"
],
"summary": "创建或执行 AI 任务",
"summary": "创建 EasyAI 媒体任务",
"parameters": [
{
"type": "boolean",
@@ -6735,7 +6741,7 @@
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "媒体任务请求,字段随任务类型变化",
"name": "input",
"in": "body",
"required": true,
@@ -6748,7 +6754,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -7548,7 +7554,7 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"description": "默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway 与 server-main EasyAIClient 的异步提交结构。",
"consumes": [
"application/json"
],
@@ -7556,9 +7562,9 @@
"application/json"
],
"tags": [
"tasks"
"media"
],
"summary": "创建或执行 AI 任务",
"summary": "创建 EasyAI 媒体任务",
"parameters": [
{
"type": "boolean",
@@ -7573,7 +7579,7 @@
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "媒体任务请求,字段随任务类型变化",
"name": "input",
"in": "body",
"required": true,
@@ -7586,7 +7592,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -7647,7 +7653,7 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"description": "默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway 与 server-main EasyAIClient 的异步提交结构。",
"consumes": [
"application/json"
],
@@ -7655,9 +7661,9 @@
"application/json"
],
"tags": [
"tasks"
"media"
],
"summary": "创建或执行 AI 任务",
"summary": "创建 EasyAI 媒体任务",
"parameters": [
{
"type": "boolean",
@@ -7672,7 +7678,7 @@
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "媒体任务请求,字段随任务类型变化",
"name": "input",
"in": "body",
"required": true,
@@ -7685,7 +7691,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -8063,15 +8069,14 @@
"application/json"
],
"tags": [
"volces-compatible"
"media"
],
"summary": "创建 server-main 兼容视频任务",
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/httpapi.TaskAcceptedResponse"
}
}
}
@@ -8084,7 +8089,7 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"description": "默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway 与 server-main EasyAIClient 的异步提交结构。",
"consumes": [
"application/json"
],
@@ -8092,9 +8097,9 @@
"application/json"
],
"tags": [
"tasks"
"media"
],
"summary": "创建或执行 AI 任务",
"summary": "创建 EasyAI 媒体任务",
"parameters": [
{
"type": "boolean",
@@ -8109,7 +8114,7 @@
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "媒体任务请求,字段随任务类型变化",
"name": "input",
"in": "body",
"required": true,
@@ -8122,7 +8127,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -8348,7 +8353,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -8397,7 +8402,7 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"description": "默认同步返回 EasyAI GeneratedResponse;设置 X-Async=true 时返回同时兼容 Gateway 与 server-main EasyAIClient 的异步提交结构。",
"consumes": [
"application/json"
],
@@ -8405,9 +8410,9 @@
"application/json"
],
"tags": [
"tasks"
"media"
],
"summary": "创建或执行 AI 任务",
"summary": "创建 EasyAI 媒体任务",
"parameters": [
{
"type": "boolean",
@@ -8422,7 +8427,7 @@
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "媒体任务请求,字段随任务类型变化",
"name": "input",
"in": "body",
"required": true,
@@ -8435,7 +8440,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.CompatibleResponse"
"$ref": "#/definitions/httpapi.EasyAIGeneratedResponse"
}
},
"202": {
@@ -9813,6 +9818,143 @@
}
}
},
"httpapi.EasyAIGeneratedResponse": {
"type": "object",
"properties": {
"cancellable": {
"type": "boolean"
},
"code": {
"type": "string"
},
"created": {
"type": "integer",
"example": 1784772000000
},
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/httpapi.EasyAIMediaOutput"
}
},
"message": {
"type": "string"
},
"output": {
"type": "array",
"items": {
"type": "string"
}
},
"output_content": {
"type": "array",
"items": {
"$ref": "#/definitions/httpapi.EasyAIMediaOutput"
}
},
"query_url": {
"type": "string",
"example": "/api/v1/ai/result/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
},
"result": {
"type": "object",
"additionalProperties": true
},
"status": {
"type": "string",
"enum": [
"submitted",
"process",
"success",
"failed"
],
"example": "success"
},
"submitted": {
"type": "boolean"
},
"taskId": {
"type": "string",
"example": "9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
},
"task_id": {
"type": "string",
"example": "9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
},
"upstream_task_id": {
"type": "string",
"example": "provider-task-123"
},
"usage": {
"type": "object",
"additionalProperties": true
}
}
},
"httpapi.EasyAIMediaOutput": {
"type": "object",
"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": {
"type": "object",
"additionalProperties": true
},
"mime_type": {
"type": "string"
},
"source_resolution": {
"type": "string"
},
"target_resolution": {
"type": "string"
},
"text": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"image",
"video",
"audio",
"file",
"text"
],
"example": "video"
},
"url": {
"type": "string",
"example": "https://cdn.example.com/output.mp4"
},
"video_url": {
"type": "string"
},
"width": {
"type": "integer"
}
}
},
"httpapi.ErrorEnvelope": {
"type": "object",
"properties": {
@@ -9854,7 +9996,7 @@
}
}
},
"httpapi.FileUploadResponse": {
"httpapi.FileUploadData": {
"type": "object",
"properties": {
"assetStorage": {
@@ -9883,6 +10025,42 @@
}
}
},
"httpapi.FileUploadResponse": {
"type": "object",
"properties": {
"assetStorage": {
"type": "object",
"additionalProperties": true
},
"contentType": {
"type": "string",
"example": "image/png"
},
"data": {
"$ref": "#/definitions/httpapi.FileUploadData"
},
"filename": {
"type": "string",
"example": "image.png"
},
"id": {
"type": "string",
"example": "file_abc123"
},
"size": {
"type": "integer",
"example": 1024
},
"status": {
"type": "string",
"example": "success"
},
"url": {
"type": "string",
"example": "/static/uploaded/upload-abc123.png"
}
}
},
"httpapi.GeminiErrorEnvelope": {
"type": "object",
"properties": {
@@ -10514,6 +10692,36 @@
}
}
},
"httpapi.OpenAIImageData": {
"type": "object",
"properties": {
"b64_json": {
"type": "string"
},
"revised_prompt": {
"type": "string"
},
"url": {
"type": "string",
"example": "https://cdn.example.com/output.png"
}
}
},
"httpapi.OpenAIImagesResponse": {
"type": "object",
"properties": {
"created": {
"type": "integer",
"example": 1710000000
},
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/httpapi.OpenAIImageData"
}
}
}
},
"httpapi.PlatformListResponse": {
"type": "object",
"properties": {
@@ -10894,12 +11102,24 @@
"next": {
"$ref": "#/definitions/httpapi.TaskNextLinks"
},
"query_url": {
"type": "string",
"example": "/api/v1/ai/result/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
},
"status": {
"type": "string",
"example": "submitted"
},
"task": {
"$ref": "#/definitions/store.GatewayTask"
},
"taskId": {
"type": "string",
"example": "9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
},
"task_id": {
"type": "string",
"example": "9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
}
}
},
@@ -10961,6 +11181,10 @@
"events": {
"type": "string",
"example": "/api/v1/tasks/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25/events"
},
"result": {
"type": "string",
"example": "/api/v1/ai/result/9f4d8f3d-5f5f-4bb7-a4be-344a9f930e25"
}
}
},