feat: harden public OpenAI API contracts
Quality gate / backend (push) Canceled after 0s
Quality gate / frontend (push) Canceled after 0s

This commit is contained in:
Xin Wang
2026-09-07 14:25:48 +08:00
parent 8025ed8aa0
commit 2649d64b55
36 changed files with 16643 additions and 236 deletions
+149
View File
@@ -0,0 +1,149 @@
---
title: OpenAI 兼容范围
description: OpenAI-compatible subset v1 的字段、事件、错误与版本兼容矩阵。
icon: brackets
---
# OpenAI-compatible subset v1
平台公开协议命名为 **OpenAI-compatible subset v1**。它兼容 OpenAI Responses 与 Realtime 的核心调用方式,但只承诺本页列出的子集;没有列为“支持”的 OpenAI 字段,不能视为已经实现。
字段分为三种状态:
| 状态 | 含义 |
| --- | --- |
| 支持 | 字段会被校验并产生文档描述的效果 |
| 平台锁定 | 能力存在,但值来自助手配置;调用方提交时返回 `immutable_configuration` 或 `immutable_session_field` |
| 不支持 | 当前版本不实现;显式提交时返回 `unsupported_parameter`、`unsupported_operation` 或 `invalid_event` |
## HTTP 资源
| 接口 | 状态 | 说明 |
| --- | --- | --- |
| `GET /v1/models` | 支持 | 返回可通过公开协议调用的 `assistant:asst_xxx` |
| `POST /v1/responses` | 支持 | 非流式 JSON 或 Responses SSE |
| `GET /v1/responses/{id}` | 支持 | 只允许创建它的长期 API Key 查询 |
| `GET /v1/responses/{id}/input_items` | 支持 | `after`、`limit`、`order` 游标分页 |
| `DELETE /v1/responses/{id}` | 支持 | 逻辑删除;既有子 Response 的祖先链仍可恢复 |
| `POST /v1/responses/{id}/cancel` | 不支持 | subset v1 不支持 background,固定返回 `unsupported_operation` |
| `POST /v1/realtime/client_secrets` | 支持 | 使用长期 Key 签发短期、绑定助手的令牌 |
| `POST /v1/realtime/calls` | 支持 | `multipart/form-data` 或原始 `application/sdp` |
| `GET /v1/realtime` WebSocket upgrade | 支持 | 服务端或自定义客户端 Realtime 连接 |
| `/v1/chat/completions` | 不支持 | 不提供旧 Chat Completions 兼容层 |
## Responses 请求字段
| 字段 | 状态 | subset v1 行为 |
| --- | --- | --- |
| `model` | 支持 | 首轮必填,格式为 `assistant:asst_xxx`;后续可继承 |
| `input` 字符串 | 支持 | 转换为一条 `user` 文本消息 |
| `input[].message` | 支持 | 仅文本 `input_text` / `output_text` |
| `input[].function_call_output` | 支持 | 只能解析父链尚未完成的 Client Tool call ID |
| `previous_response_id` | 支持 | 恢复祖先上下文,允许从同一父节点分支 |
| `stream` | 支持 | `false` 返回 JSON;`true` 返回 SSE |
| `store` | 支持但固定 | 只能省略或为 `true` |
| `x_interactive_media.variables` | 支持 | 首轮赋值,后续继承并增量覆盖 |
| `instructions` | 平台锁定 | 来自助手配置 |
| `tools`、`tool_choice` | 平台锁定 | 来自助手及工具绑定 |
| `background`、`conversation` | 不支持 | 状态只通过 `previous_response_id` 管理 |
| `include`、`reasoning`、`text` | 不支持 | 显式拒绝,不静默忽略 |
| `temperature`、`top_p`、`truncation` | 不支持 | 由底层助手和模型资源控制 |
| 图片、文件输入 | 不支持 | 文本接口只接受文本;实时图片走 Realtime item |
Response 返回标准 `response` 对象。`output` 当前可能包含 `message` 或 `function_call`。如果底层 Provider 能稳定提供 token 统计,`usage` 返回真实值;当前无法取得时明确返回 `null`,不会估算。
## Responses SSE 事件
| 事件 | 状态 | 顺序约束 |
| --- | --- | --- |
| `response.created` | 支持 | 第一个事件 |
| `response.in_progress` | 支持 | 紧随 created |
| `response.output_item.added` / `done` | 支持 | 每个输出项各一组 |
| `response.content_part.added` / `done` | 支持 | 文本输出项使用 |
| `response.output_text.delta` / `done` | 支持 | delta 为零到多个,done 恰好一个 |
| `response.function_call_arguments.delta` / `done` | 支持 | Client Tool 参数使用;done 恰好一个 |
| `response.completed` | 支持 | 正常终态,最后一个事件 |
| `error` + `response.failed` | 支持 | 失败终态 |
每个事件都有从 `0` 开始单调递增的 `sequence_number`。流式终态、同一 Response 的非流式结果和随后 GET 的资源语义一致。
## Realtime 客户端事件
以下客户端事件属于 Core 支持范围:
- `session.update`
- `conversation.item.create`
- `conversation.item.truncate`
- `input_audio_buffer.append`
- `input_audio_buffer.commit`
- `input_audio_buffer.clear`
- `output_audio_buffer.clear`
- `response.create`
- `response.cancel`
会话中的 `model`、`instructions`、`voice`、`tools` 和 `tool_choice` 为平台锁定字段。`output_modalities` 与 Server VAD / PTT 参数可更新。WebSocket 支持 Base64 PCM16 音频;WebRTC 音频走媒体轨道,事件走 `oai-events` DataChannel。连续视频只通过协商后的 WebRTC video track 提供。
服务端事件的完整名称与最小 envelope 由仓库中的 `backend/contracts/openai-realtime-server-events.schema.json` 定义;客户端事件由 `backend/contracts/openai-realtime-client-events.schema.json` 定义。
## Interactive Media Extensions v1
所有扩展事件都使用 `x.interactive_media.*` 命名空间,并独立版本化为字符串 `"1"`。
客户端先协商能力:
```json
{
"type": "x.interactive_media.capabilities.update",
"event_id": "evt_caps_001",
"version": "1",
"capabilities": ["dynamic_variables", "workflow_events"]
}
```
服务端以 `x.interactive_media.capabilities.updated` 返回 `capabilities`、`rejected` 和实际 `version`。只有协商成功后,服务端才发送相应扩展事件。当前能力为:
| capability | 作用 |
| --- | --- |
| `dynamic_variables` | 运行中更新声明过的动态变量 |
| `workflow_events` | 接收节点、业务事件、变量和错误事件 |
| `handoff` | 接收人工接管和通话结束事件 |
| `video_track` | 协商项目扩展的 WebRTC 视频轨道 |
扩展事件缺少版本或使用未知版本时返回 `invalid_event`;未知 capability 会出现在 `rejected` 中,不会被静默启用。
## 错误与状态码
所有公开 HTTP 错误统一返回:
```json
{
"error": {
"type": "invalid_request_error",
"code": "response_not_ready",
"message": "Previous response is in_progress",
"param": "previous_response_id"
}
}
```
| HTTP 状态 | 使用规则 |
| --- | --- |
| `400` | schema 合法但字段不支持、平台锁定或业务语义无效 |
| `401` | Bearer Key 缺失、无效、过期,或令牌类型不适用于接口 |
| `404` | 资源不存在、已删除或属于另一个 API Key |
| `409` | 父响应未结束、幂等键冲突或资源状态冲突 |
| `422` | JSON、路径或查询参数不符合公开 schema |
| `429` | 请求、并发或容量限制;当前为预留标准状态 |
| `500` | 运行中不可恢复的内部失败 |
| `503` | 服务暂时不能接收请求;当前为预留标准状态 |
| `504` | Responses 生成超过服务端超时 |
每个 HTTP 响应都带 `X-Request-ID`。调用方传入符合格式的 ID 时服务端透传,否则生成 `req_...`。Realtime `error` 事件中的 `error.event_id` 指向导致错误的客户端 `event_id`。
## 兼容性规则
- subset v1 内新增可选字段、可选事件字段和新错误码属于向后兼容变更。
- 新增必须由调用方主动使用的扩展 capability 属于向后兼容变更。
- 删除字段、改变字段含义、改变既有事件顺序或把可选字段改为必填,必须升级协议主版本。
- 平台锁定或不支持的字段转为支持,可以在 v1 内发布,但必须同步 schema、兼容矩阵、示例和 SDK 契约测试。
- 废弃项至少在开发者文档中标记一个发布周期;破坏性变更不得在原版本中静默上线。