feat(gateway): add Codex Live transport

This commit is contained in:
ZheFox
2026-08-20 21:59:05 +08:00
parent 6916e9da76
commit 4185ad1b1e
35 changed files with 6683 additions and 85 deletions
@@ -134,6 +134,7 @@ const STANDARD_UPSTREAM_WEBSOCKET_ERRORS: UpstreamWebSocketErrorCodes =
UpstreamWebSocketErrorCodes {
upstream_url_missing: "responses_upstream_url_missing",
upstream_url_invalid: "responses_upstream_url_invalid",
frontdoor_self_loop: "responses_websocket_frontdoor_self_loop",
headers_invalid: "responses_websocket_headers_invalid",
client_build_failed: "responses_websocket_client_build_failed",
proxy_invalid: "responses_websocket_proxy_invalid",
@@ -215,6 +216,10 @@ mod tests {
adapter.upstream_errors().handshake_failed,
"responses_websocket_handshake_failed"
);
assert_eq!(
adapter.upstream_errors().frontdoor_self_loop,
"responses_websocket_frontdoor_self_loop"
);
}
#[test]
@@ -24,6 +24,7 @@ const CODEX_WEBSOCKET_RATE_LIMITS_REPORT_CONTEXT_FIELD: &str = "codex_websocket_
const CODEX_UPSTREAM_WEBSOCKET_ERRORS: UpstreamWebSocketErrorCodes = UpstreamWebSocketErrorCodes {
upstream_url_missing: "codex_upstream_url_missing",
upstream_url_invalid: "codex_upstream_url_invalid",
frontdoor_self_loop: "codex_websocket_frontdoor_self_loop",
headers_invalid: "codex_websocket_headers_invalid",
client_build_failed: "codex_websocket_client_build_failed",
proxy_invalid: "codex_websocket_proxy_invalid",
@@ -259,6 +260,16 @@ mod tests {
ResponsesWebSocketRebindSafety, ResponsesWebSocketRelayDirective,
};
#[test]
fn codex_adapter_has_a_distinct_frontdoor_self_loop_error() {
let adapter = CodexResponsesWebSocketAdapter;
assert_eq!(
adapter.upstream_errors().frontdoor_self_loop,
"codex_websocket_frontdoor_self_loop"
);
}
#[test]
fn codex_rate_limit_chunk_is_kept_for_the_terminal_report() {
let adapter = CodexResponsesWebSocketAdapter;
@@ -16,7 +16,7 @@ use crate::provider_pool_demand::{
use crate::upstream_admission::UpstreamTargetAdmissionPermit;
use crate::{AppState, GatewayError};
pub(super) struct ResponsesWebSocketTurnAdmission {
pub(crate) struct ResponsesWebSocketTurnAdmission {
upstream_execution: Option<aether_runtime::ConcurrencyPermit>,
upstream_target: Option<UpstreamTargetAdmissionPermit>,
provider_pool: Option<ProviderPoolInFlightGuard>,
@@ -24,7 +24,7 @@ pub(super) struct ResponsesWebSocketTurnAdmission {
}
impl ResponsesWebSocketTurnAdmission {
pub(super) async fn acquire(
pub(crate) async fn acquire(
state: &AppState,
plan: &ExecutionPlan,
trace_id: &str,
@@ -61,7 +61,7 @@ impl ResponsesWebSocketTurnAdmission {
/// Release the distributed provider token before the turn's persistence
/// work. The remaining permits are local RAII guards and are dropped with
/// this value.
pub(super) async fn release(mut self) {
pub(crate) async fn release(mut self) {
if let Some(provider_pool) = self.provider_pool.take() {
provider_pool.release().await;
}
@@ -29,6 +29,8 @@ mod turn;
mod turn_state;
mod upstream;
pub(crate) use admission::ResponsesWebSocketTurnAdmission;
use std::net::SocketAddr;
use axum::body::Body;