feat(api): 统一官方兼容接口响应协议
ci / verify (pull_request) Failing after 15s

兼容接口现在以入口协议作为最终响应协议,同协议保留官方 Wire 响应,跨协议统一转换成功、任务状态与错误结构。

同时修正异步提交状态边界,持久化兼容公开任务标识和官方提交响应,并新增迁移、流式响应及协议契约测试。

验证:go vet ./...;go test ./...;govulncheck ./...;pnpm lint;pnpm test;pnpm build;pnpm audit --audit-level high;pnpm openapi;全部 CI 脚本。
This commit is contained in:
2026-07-22 15:11:50 +08:00
parent cbebfd7baa
commit a778216264
32 changed files with 2436 additions and 591 deletions
+327 -163
View File
@@ -5460,43 +5460,43 @@
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"402": {
"description": "Payment Required",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"429": {
"description": "Too Many Requests",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
}
}
@@ -5523,6 +5523,18 @@
"type": "object",
"additionalProperties": true
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
}
}
},
@@ -5547,8 +5559,31 @@
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/httpapi.VolcesContentsGenerationTaskResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
},
"429": {
"description": "Too Many Requests",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
}
}
@@ -5572,8 +5607,13 @@
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/httpapi.VolcesContentsGenerationTaskResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
}
}
@@ -5596,8 +5636,13 @@
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
"$ref": "#/definitions/httpapi.VolcesContentsGenerationTaskResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.VolcesErrorEnvelope"
}
}
}
@@ -5610,7 +5655,6 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"consumes": [
"application/json"
],
@@ -5618,24 +5662,12 @@
"application/json"
],
"tags": [
"tasks"
"embeddings"
],
"summary": "创建或执行 AI 任务",
"summary": "创建 OpenAI Embeddings",
"parameters": [
{
"type": "boolean",
"description": "true 时异步创建任务并返回 202",
"name": "X-Async",
"in": "header"
},
{
"type": "string",
"description": "可选请求幂等键;同一用户范围内唯一",
"name": "Idempotency-Key",
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "OpenAI Embeddings 请求",
"name": "input",
"in": "body",
"required": true,
@@ -5651,52 +5683,28 @@
"$ref": "#/definitions/httpapi.CompatibleResponse"
}
},
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/httpapi.TaskAcceptedResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"402": {
"description": "Payment Required",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"429": {
"description": "Too Many Requests",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
}
}
@@ -5903,7 +5911,6 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"consumes": [
"application/json"
],
@@ -5911,24 +5918,12 @@
"application/json"
],
"tags": [
"tasks"
"images"
],
"summary": "创建或执行 AI 任务",
"summary": "创建或编辑 OpenAI Images",
"parameters": [
{
"type": "boolean",
"description": "true 时异步创建任务并返回 202",
"name": "X-Async",
"in": "header"
},
{
"type": "string",
"description": "可选请求幂等键;同一用户范围内唯一",
"name": "Idempotency-Key",
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "OpenAI Images 请求",
"name": "input",
"in": "body",
"required": true,
@@ -5944,52 +5939,28 @@
"$ref": "#/definitions/httpapi.CompatibleResponse"
}
},
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/httpapi.TaskAcceptedResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"402": {
"description": "Payment Required",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"429": {
"description": "Too Many Requests",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
}
}
@@ -6002,7 +5973,6 @@
"BearerAuth": []
}
],
"description": "统一公开入口按 model 选择平台模型并默认同步返回兼容响应;设置 X-Async=true 时异步创建任务并返回 202。",
"consumes": [
"application/json"
],
@@ -6010,24 +5980,12 @@
"application/json"
],
"tags": [
"tasks"
"images"
],
"summary": "创建或执行 AI 任务",
"summary": "创建或编辑 OpenAI Images",
"parameters": [
{
"type": "boolean",
"description": "true 时异步创建任务并返回 202",
"name": "X-Async",
"in": "header"
},
{
"type": "string",
"description": "可选请求幂等键;同一用户范围内唯一",
"name": "Idempotency-Key",
"in": "header"
},
{
"description": "AI 任务请求,字段随任务类型变化",
"description": "OpenAI Images 请求",
"name": "input",
"in": "body",
"required": true,
@@ -6043,52 +6001,28 @@
"$ref": "#/definitions/httpapi.CompatibleResponse"
}
},
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/httpapi.TaskAcceptedResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"402": {
"description": "Payment Required",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"429": {
"description": "Too Many Requests",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
}
}
@@ -6181,7 +6115,7 @@
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.KlingErrorEnvelope"
}
}
}
@@ -6283,7 +6217,7 @@
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.KlingErrorEnvelope"
}
}
}
@@ -6495,7 +6429,8 @@
"application/json"
],
"produces": [
"application/json"
"application/json",
"text/event-stream"
],
"tags": [
"gemini-compatible"
@@ -6531,25 +6466,98 @@
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
}
}
}
},
"/api/v1/models/{model}:streamGenerateContent": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "使用统一 /api/v1 前缀接收 Gemini generateContent 请求;旧 /v1 和 /v1beta 路径保留兼容。",
"consumes": [
"application/json"
],
"produces": [
"application/json",
"text/event-stream"
],
"tags": [
"gemini-compatible"
],
"summary": "Gemini generateContent 兼容接口",
"parameters": [
{
"type": "string",
"description": "模型名称",
"name": "model",
"in": "path",
"required": true
},
{
"description": "Gemini generateContent 请求",
"name": "input",
"in": "body",
"required": true,
"schema": {
"type": "object",
"additionalProperties": true
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object",
"additionalProperties": true
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
},
"502": {
"description": "Bad Gateway",
"schema": {
"$ref": "#/definitions/httpapi.GeminiErrorEnvelope"
}
}
}
@@ -7284,42 +7292,36 @@
"description": "OK",
"schema": {
"$ref": "#/definitions/httpapi.ResponsesCompatibleResponse"
},
"headers": {
"X-Gateway-Task-Id": {
"type": "string",
"description": "网关审计任务 ID"
}
}
},
"400": {
"description": "invalid_previous_response_id / unsupported_response_tool / unsupported_response_parameter",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"402": {
"description": "Payment Required",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
},
"503": {
"description": "response_chain_unavailable",
"schema": {
"$ref": "#/definitions/httpapi.ErrorEnvelope"
"$ref": "#/definitions/httpapi.OpenAIErrorEnvelope"
}
}
}
@@ -9568,6 +9570,38 @@
}
}
},
"httpapi.GeminiErrorEnvelope": {
"type": "object",
"properties": {
"error": {
"$ref": "#/definitions/httpapi.GeminiErrorStatus"
}
}
},
"httpapi.GeminiErrorStatus": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"example": 400
},
"details": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": {}
}
},
"message": {
"type": "string",
"example": "Invalid argument"
},
"status": {
"type": "string",
"example": "INVALID_ARGUMENT"
}
}
},
"httpapi.HealthResponse": {
"type": "object",
"properties": {
@@ -9759,6 +9793,26 @@
}
}
},
"httpapi.KlingErrorEnvelope": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"example": 1001
},
"error": {
"type": "string",
"example": "invalid_parameter"
},
"message": {
"type": "string",
"example": "invalid parameter"
},
"request_id": {
"type": "string"
}
}
},
"httpapi.ModelCatalogFilterOption": {
"type": "object",
"properties": {
@@ -10052,6 +10106,35 @@
}
}
},
"httpapi.OpenAIErrorEnvelope": {
"type": "object",
"properties": {
"error": {
"$ref": "#/definitions/httpapi.OpenAIErrorPayload"
}
}
},
"httpapi.OpenAIErrorPayload": {
"type": "object",
"properties": {
"code": {
"type": "string",
"example": "invalid_parameter"
},
"message": {
"type": "string",
"example": "Invalid parameter"
},
"param": {
"type": "string",
"example": "model"
},
"type": {
"type": "string",
"example": "invalid_request_error"
}
}
},
"httpapi.PlatformListResponse": {
"type": "object",
"properties": {
@@ -10693,6 +10776,67 @@
}
}
},
"httpapi.VolcesContentsGenerationTaskResponse": {
"type": "object",
"properties": {
"content": {
"type": "object",
"additionalProperties": {}
},
"created_at": {
"type": "integer"
},
"error": {
"type": "object",
"additionalProperties": {}
},
"id": {
"type": "string",
"example": "cgt-202607221234"
},
"model": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"queued",
"running",
"succeeded",
"failed",
"cancelled"
]
},
"updated_at": {
"type": "integer"
},
"usage": {
"type": "object",
"additionalProperties": {}
}
}
},
"httpapi.VolcesErrorEnvelope": {
"type": "object",
"properties": {
"error": {
"$ref": "#/definitions/httpapi.VolcesErrorPayload"
}
}
},
"httpapi.VolcesErrorPayload": {
"type": "object",
"properties": {
"code": {
"type": "string",
"example": "invalid_parameter"
},
"message": {
"type": "string",
"example": "model is required"
}
}
},
"httpapi.WalletAdjustmentResponse": {
"type": "object",
"properties": {
@@ -12162,6 +12306,26 @@
"cancellable": {
"type": "boolean"
},
"compatibilityProtocol": {
"type": "string"
},
"compatibilityPublicId": {
"type": "string"
},
"compatibilitySourceProtocol": {
"type": "string"
},
"compatibilitySubmitBody": {
"type": "object",
"additionalProperties": {}
},
"compatibilitySubmitHeaders": {
"type": "object",
"additionalProperties": {}
},
"compatibilitySubmitHttpStatus": {
"type": "integer"
},
"conversationId": {
"type": "string"
},