fix(openai): align downstream requests with Codex protocol (#117)

Centralize downstream SDK, browser and proxy header compatibility in the
OpenAI provider. Normalize the session header alias and isolate known
non-Codex body parameters while preserving ordinary extensions.

Align account installation metadata with Codex Core and remove unverified
identity header classifications. Cover HTTP and WebSocket behavior and
document the request boundaries.

Validation: 1,105 scoped and architecture tests, Rustfmt and strict scoped
Clippy passed. Four real-account HTTP/WebSocket cases passed on gpt-5.5,
including connection reuse. Earlier gpt-reserve overload failures were
recorded separately without changing production retry policy.

Co-authored-by: Clarence <1297529513@qq.com>
Co-authored-by: Zyy <zyycn@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Clarence12138
2026-09-17 00:30:52 +08:00
committed by GitHub
co-authored by Clarence Zyy Codex
parent dac57a81c6
commit 1e6d69a349
21 changed files with 941 additions and 488 deletions
+18
View File
@@ -169,6 +169,24 @@ Responses 不透传下游的逐跳头、反代元数据(如 `cf-*`、`x-forwar
API Key 上游还会移除 Cookie、ChatGPT 账号身份、`x-codex-*`、`x-openai-internal-*`、会话/线程身份头及
`X-OpenAI-Actor-Authorization`,避免把 OAuth 或网关托管身份传给第三方 API。
Responses 也不透传 `x-stainless-*`、`Origin`、`Referer`、`sec-ch-ua*` 和 `sec-fetch-*`
携带的下游 SDK/浏览器环境或页面来源。兼容基准是 Codex Core/Desktop 请求协议;
OpenAI 官方 SDK 也会发送 `x-stainless-*`,浏览器字段也有标准定义,过滤不表示这些头非法。
规则不依赖下游 User-Agent,也不改变原始入站请求供 CORS、鉴权和本地观测使用的字段。
`session_id` 请求头仅作为入站会话别名,提取后不再原样透传,上游通过 `session-id` 表达;
两者同时存在时仍优先使用 `session-id`。正文中的 `client_metadata.session_id`、
`prompt_cache_key` 不受这条请求头规则影响。
`thread-id`、turn metadata 等 Codex 协议字段及未知业务扩展继续按既有合同处理;
`traceparent`、`tracestate` 不因属于追踪字段而被删除。
Responses 上游编码会移除 Codex 不接受的顶层 `temperature`、`max_output_tokens` 和
`prompt_cache_retention`;这些参数可能来自 Pi 等客户端的普通 OpenAI Responses 适配。
`prompt_cache_key`、`reasoning`、`include` 等 Codex 参数继续保留。过滤只作用于顶层,
不删除工具参数 schema、输入内容或 `client_metadata` 内的同名业务字段;其他未知字段继续透传。
这不是客户端匿名化:系统提示词、工具定义、工具结果、工作目录及其他业务 metadata 仍可能
透露客户端环境,网关不对正文做客户端品牌清洗。
Responses WebSocket 仅接受文本 `response.create`,同一连接串行执行。当前响应期间收到的后续业务帧
留在有界接收队列中,待当前响应完成终结和写出后再逐条校验、准入与执行,不因请求提前到达而断开。
接收队列容量为 32 个事件,超载仍关闭连接;Ping/Pong、客户端关闭和服务关闭不等待队列中的请求执行。
+11 -3
View File
@@ -195,9 +195,17 @@ API Key 默认 HTTP/SSE,可选 WS 优先;选号先验证传输资格,WS po
- OpenAI 是透明边界。Responses 请求保留未知字段和字段顺序;SSE、WebSocket、Images 与 standalone
Search 的业务正文按原始字节转发。canonical facts 从同一数据旁路提取,只用于路由、观测和计费。
- Responses 的业务扩展头保留原始多值字节;传输与反代请求头分类由 `gateway-protocol` 统一定义,
API 入站与 OpenAI Provider 编码共同使用。下游链路元数据和压缩协商不跨越该边界,
上游认证、请求画像与传输字段仍由 Provider 生成;响应方向的诊断头不受请求过滤规则影响。
- Responses 的业务扩展头保留原始多值字节。API 负责剥离鉴权、账号身份和 HTTP 传输字段,
并提取会话语义;`gateway-protocol` 共享 HTTP 传输与网关链路字段分类。客户端兼容规则集中在
`providers/openai/src/transport/downstream/`:`headers.rs` 管理下游环境头和已提取语义的头部别名,
`body.rs` 管理不适用于 Codex Responses 的已知顶层参数;兼容基准为 Codex Core/Desktop 请求协议,
不持有账号身份保护或会话规范化逻辑。OpenAI 官方 SDK 的
`x-stainless-*` 也描述下游 SDK 环境;字段合法性与是否跨链路透传是不同判断。
Provider 在 `transport/request.rs` 解码不透明头时组合兼容、身份与 HTTP 规则,
同时调用正文兼容规则;HTTP/SSE 与 WebSocket 共用此边界。
`transport/headers.rs` 负责上游身份保护和官方头组装。
会话别名只规范化请求头,不清除正文身份字段;未知业务扩展与响应诊断头不受影响,字段见
[Responses 合同](api.md#3-openai-数据面与模型目录)。提示词、工具及业务正文不做客户端品牌清洗。
- xAI 是翻译边界。Provider 把 Grok wire 转换为 Responses wire;上游结构化错误的 message/code/type
可以透出,但账号指纹会先脱敏。
- response ID 是不透明 UTF-8 bytes,不假设 UUID、固定长度或跨 Provider 可复用。