mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
feat(plugins): add provider request composition middleware (#511)
* feat(plugins): add provider request composition middleware Expose per-attempt provider parameters and a final outbound preparation chain using middleware v6. Preserve native transport behavior when no outbound scope matches. Co-authored-by: Codex <noreply@openai.com> * fix(plugins): sync workbench with middleware v6 Co-authored-by: Codex <noreply@openai.com> --------- Co-authored-by: Zyy <zyycn@users.noreply.github.com> Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
+14
-8
@@ -308,14 +308,16 @@ Responses 也不透传 `x-stainless-*`、`Origin`、`Referer`、`sec-ch-ua*` 和
|
||||
出站移除下游的 `traceparent`、`tracestate` 及 WS metadata 中对应的
|
||||
`ws_request_header_traceparent`、`ws_request_header_tracestate`
|
||||
|
||||
会话、线程、窗口及父子线程引用在出站时按账号安装身份稳定映射为 UUID;
|
||||
同账号保留引用关系,换账号使用不同标识。HTTP 请求头、正文 metadata、WS 副本及
|
||||
会话、线程、窗口及父子线程引用在出站时按本次安装身份稳定映射为 UUID;
|
||||
默认使用账号安装身份,同账号保留引用关系,换账号使用不同标识。HTTP 请求头、正文 metadata、WS 副本及
|
||||
已识别的 Desktop 自动 Git 上下文使用一致映射。
|
||||
轮次及父子轮次引用保留客户端原值,包括输入项的 `internal_chat_message_metadata_passthrough.turn_id`、
|
||||
请求 metadata 中的 `turn_id`、`parent_turn_id`、`root_turn_id`,以及 `x-client-turn-id`、
|
||||
Images 的 `x-codex-image-turn-id` 和 Desktop 自动 Git 上下文的 `clientUserMessageId`。
|
||||
输入项元数据保持不变。Search 的会话 `id` 按同一账号域映射,只替换该值的原始字节,其余正文保持不变。
|
||||
`prompt_cache_key` 同样按账号映射,保留同账号内的缓存共享关系;未提供时不补造。
|
||||
输入项元数据保持不变。Search 的会话 `id` 按同一安装身份域映射,只替换该值的原始字节,其余正文保持不变。
|
||||
`prompt_cache_key` 同样按安装身份映射,保留同一身份内的缓存共享关系;未提供时不补造。
|
||||
受信任插件可通过 attempt 构造参数选择本次安装身份;参数只影响出站构造,不改变实际选号与计费归属,
|
||||
详见 [SDK 请求构造参数](../backend/crates/gateway-plugin/sdk/docs/capabilities.md#模型请求与-attempt)。
|
||||
续接 response ID、历史 item/call ID、业务正文和未知扩展不参与映射,
|
||||
该处理减少显式追踪标识的跨账号复用,不保证会话内容或业务 metadata 无法关联
|
||||
|
||||
@@ -473,7 +475,7 @@ Images 排除已知为 Free 套餐的 OAuth 账号;套餐缺失或未知时不
|
||||
|
||||
`/v1/alpha/search` 使用相同的 OpenAI Provider 原生端点边界:模型不映射,正文除会话 `id` 的账号归一及显式请求策略外原样转发,
|
||||
Provider 旁路读取请求中的 `model`,按[账号模型限制](#账号模型限制)选号。
|
||||
`x-codex-turn-metadata` 在移除客户端账号身份并按当前 lease 重写 installation ID 后转发;上游账号
|
||||
`x-codex-turn-metadata` 在移除客户端账号身份并按本次构造参数重写 installation ID 后转发;上游账号
|
||||
Authorization、Cookie、account ID、originator 和 User-Agent 均由代理安全重建。
|
||||
Images 与 Search 保留通过现有过滤规则的普通业务请求头及多值字节;Responses 原连接的 turn state
|
||||
不随独立端点转发,turn metadata 仍由所属端点按当前账号处理。
|
||||
@@ -612,7 +614,7 @@ OpenAI 选号阶段确认本次可选账号全部额度耗尽时,HTTP 返回 `
|
||||
引导、sideband 与 hangup 的业务扩展头默认透传;认证、账号身份、下游环境与传输头遵守
|
||||
[请求头与身份](#请求头与身份)边界。`X-Session-Id`、`Voice-Session-Id` 是 Live 业务会话标识,原样透传。
|
||||
`Session-Id`、`Thread-Id` 等已识别追踪标识按选中账号的安装身份稳定映射,同账号各阶段保持一致,
|
||||
换账号使用不同标识;客户端 trace 被剥离。
|
||||
换账号使用不同标识;客户端 trace 被剥离。创建请求可由 attempt 插件改写本次构造身份,后续 sideband / hangup 仍使用钉住账号的身份。
|
||||
Live 不继承 Responses 的路由提示与续接状态;turn metadata 中的原账号绑定信息清理后保留其他字段。
|
||||
真实 call ID 保留用于钉住账号访问通话。HTTP 业务头保留原始多值字节,sideband 握手沿用 WebSocket 可编码的头值
|
||||
|
||||
@@ -2527,9 +2529,13 @@ GitHub 的 `location` 使用 `kind: "github"`、`repository: "owner/repo"`、`ta
|
||||
`model_catalog`、`management`、`command_line` 和 `maintenance` 按清单声明注册,不接受 binding;
|
||||
`frontend_authentication` 必须由管理员显式配置身份映射,也不自动创建
|
||||
|
||||
`middleware` v5 可绑定 `http`、`websocket`、`service`、`request` 和 `attempt`,按声明的挂载阶段分别配置。
|
||||
`middleware` v6 可绑定 `http`、`websocket`、`service`、`request`、`attempt` 和 `outbound`,按声明的挂载阶段分别配置。
|
||||
`http`、`websocket` 和 `service` 不使用 Key、分组、Provider 或模型范围,这些数组必须为空;插件在处理器内匹配路径、消息或服务操作。
|
||||
`request` 与 `routing` 支持 Key、分组和公开模型范围,Provider 范围必须为空;`attempt`、`upstream`、`scheduling`、`retry` 与 `observation` 可使用 Provider 范围
|
||||
`request` 与 `routing` 支持 Key、分组和公开模型范围,Provider 范围必须为空;`attempt`、`outbound`、`upstream`、`scheduling`、`retry` 与 `observation` 可使用 Provider 范围
|
||||
|
||||
`outbound` 准备原生 Provider 交给 transport 的请求,覆盖 OpenAI Responses HTTP / WS、Images、Search、Live 创建及 xAI 生成与压缩。
|
||||
它使用最终上游模型匹配范围,下一层返回准备后的请求,不执行发送;字节、headers、HTTP 方法和目标的合同见 [SDK 出站请求准备](../backend/crates/gateway-plugin/sdk/docs/capabilities.md#上游出站准备)。
|
||||
该阶段不包括 OAuth、额度刷新等后台请求,也不包括由 `upstream_adapter` 自行执行的发送
|
||||
|
||||
`observer` 固定使用 `observation/observe`,必填 `event` 为 `request_completed` 或 `websocket_response`。
|
||||
每种事件最多一条绑定,可分别设置请求范围;同一实例两类事件的 `order` 必须相同。其他能力不接受非空 `event`。
|
||||
|
||||
+12
-2
@@ -167,11 +167,20 @@ flowchart LR
|
||||
|
||||
- **策略与中间件独立编译**:Runtime 的 `adapter/policy` 负责路由、调度与重试;`adapter/middleware` 负责各挂载边界的选择和组合,协议模块负责单层调用及正文生命周期
|
||||
- **数据加工走中间件**:Core 的类型化 `compose` 统一维护顺序与单次续体;Runtime 发布时按挂载边界编译有序候选,调用时仅在当前候选中匹配作用域、捕获上下文并拼接续体,协议适配器负责单层 RPC 与资源投影。
|
||||
接入按 HTTP、WebSocket 消息、逻辑请求、上游尝试和主动服务调用的生命周期边界组织。API 在路由匹配前组合所有公开 HTTP 接口;
|
||||
接入按 HTTP、WebSocket 消息、逻辑请求、上游尝试、出站准备和主动服务调用的生命周期边界组织。API 在路由匹配前组合所有公开 HTTP 接口;
|
||||
`http` 可改写路径、方法、完整 headers、惰性上传与响应流,也可直接返回新路由结果或接管自定义 WebSocket 升级。
|
||||
握手、socket 与断连由 API 持有,会话处理通过原 RPC 资源流保活;HTTP 返回链替换响应时释放未提交的会话。
|
||||
原生与插件接管的下游 WebSocket 共用消息组合和取消入口,在默认解析前和实际写入前处理完整消息;读写并发进行,插件调用期间不占用 transport 写锁。
|
||||
`request` 包裹逻辑模型请求,`attempt` 包裹每次已选号的执行;请求顺序进入、响应逆序返回。
|
||||
attempt 可携带 Provider 的本次构造参数,Core / Runtime 只传递完整替换后的对象,解释和缺失校验由 Provider 负责;
|
||||
参数不改变真实租约、凭据版本和计费归属,也不承载宿主对插件策略的推断、补值或持久化。
|
||||
`outbound` 在原生默认值、隐私处理、序列化及内容压缩之后组合完整请求,续体只准备值,Provider 在整条返回链结束后发送。
|
||||
无绑定或未命中当前请求范围时保留原生请求构造,不进入出站准备链。
|
||||
它复用本次 attempt 的冻结计划、取消、期限和副作用水位;Provider 不再次应用业务默认值或重写正文,插件负责报文与内容编码的一致性。
|
||||
原生 HTTP 客户端的默认行为仍生效,包括 reqwest 对缺省 Accept 的补齐,具体边界见 [SDK 出站准备](../backend/crates/gateway-plugin/sdk/docs/capabilities.md#上游出站准备)。
|
||||
HTTP 方法、目标、重复头与原始正文由插件显式替换,仍须符合实际 transport 的格式与端点合同;xAI 的官方端点和 DNS 策略由其 transport 保留。
|
||||
WS 每轮准备候选 opening 与完整消息,新响应链按 opening 改写区分连接池项;精确续接使用实际拥有该链的连接,不重连或重放以兑现候选握手。
|
||||
Cookie 归属读取真实响应或 opening 地址,账号租约、凭据版本、已发送状态和续接事实仍由原 owner 持有。
|
||||
中间件读取和改写完整 headers、正文及响应帧,不进行字段裁剪或额外读取授权;响应正文按需读取,转换和改写保留 Core 的交付、取消与结算事实。
|
||||
Provider 来源与执行事件快照可由插件读取,包含费用明细、上游观测、会话状态和原始 wire;读取快照不转移计量和资源所有权。
|
||||
数据面插件通过受管 HTTP 已发送、无法证明未发送,或进入主动 HTTP/公开服务调用链时,Runtime 把该事实并入 Core 的请求副作用水位,后续不能按
|
||||
@@ -457,7 +466,8 @@ OpenAI 模型目录用于发现,不因目录缺项拒绝请求;管理员配
|
||||
|
||||
- OpenAI 是透明边界。正文兼容、身份归一和显式请求策略之外的业务字段保留原始语义;
|
||||
业务响应按原始字节转发,客户端错误兼容与原生续写额度恢复按明确例外处理,见 [OpenAI 透传](api.md#openai-透传)。
|
||||
`transport/correlation` 在出站副本上统一映射账号关联标识并剥离客户端 trace,
|
||||
`transport/correlation` 在出站副本上按本次安装身份统一映射关联标识并剥离客户端 trace;
|
||||
安装身份默认取自账号,可由 attempt 的构造参数改写,缺失或非法结果不回退默认值。
|
||||
内部选号、亲和、连接池与本地诊断继续读取原始身份;具体字段边界见 [API 协议](api.md#请求头与身份)
|
||||
canonical facts 从同一数据旁路提取,用于路由、恢复判断、观测和计费。
|
||||
WebSocket transport 按完整文本消息交付,wire 同时保留原文与可选解析视图;同协议出口使用原文,
|
||||
|
||||
Reference in New Issue
Block a user