Request compression is no longer tied to the provider

This commit is contained in:
Channing Conger
2026-01-05 12:41:12 -08:00
parent 47366e8417
commit f5adf8291a
22 changed files with 84 additions and 100 deletions
+18 -4
View File
@@ -6,6 +6,7 @@ use crate::common::ResponseStream;
use crate::endpoint::streaming::StreamingClient;
use crate::error::ApiError;
use crate::provider::Provider;
use crate::provider::RequestCompression;
use crate::provider::WireApi;
use crate::sse::chat::spawn_chat_stream;
use crate::telemetry::SseTelemetry;
@@ -45,8 +46,13 @@ impl<T: HttpTransport, A: AuthProvider> ChatClient<T, A> {
}
}
pub async fn stream_request(&self, request: ChatRequest) -> Result<ResponseStream, ApiError> {
self.stream(request.body, request.headers).await
pub async fn stream_request(
&self,
request: ChatRequest,
request_compression: RequestCompression,
) -> Result<ResponseStream, ApiError> {
self.stream(request.body, request.headers, request_compression)
.await
}
pub async fn stream_prompt(
@@ -55,6 +61,7 @@ impl<T: HttpTransport, A: AuthProvider> ChatClient<T, A> {
prompt: &ApiPrompt,
conversation_id: Option<String>,
session_source: Option<SessionSource>,
request_compression: RequestCompression,
) -> Result<ResponseStream, ApiError> {
use crate::requests::ChatRequestBuilder;
@@ -64,7 +71,7 @@ impl<T: HttpTransport, A: AuthProvider> ChatClient<T, A> {
.session_source(session_source)
.build(self.streaming.provider())?;
self.stream_request(request).await
self.stream_request(request, request_compression).await
}
fn path(&self) -> &'static str {
@@ -78,9 +85,16 @@ impl<T: HttpTransport, A: AuthProvider> ChatClient<T, A> {
&self,
body: Value,
extra_headers: HeaderMap,
request_compression: RequestCompression,
) -> Result<ResponseStream, ApiError> {
self.streaming
.stream(self.path(), body, extra_headers, spawn_chat_stream)
.stream(
self.path(),
body,
extra_headers,
request_compression,
spawn_chat_stream,
)
.await
}
}
+1 -2
View File
@@ -90,7 +90,7 @@ struct CompactHistoryResponse {
#[cfg(test)]
mod tests {
use super::*;
use crate::provider::RequestCompression;
use crate::provider::RetryConfig;
use async_trait::async_trait;
use codex_client::Request;
@@ -137,7 +137,6 @@ mod tests {
retry_5xx: true,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: Duration::from_secs(1),
}
}
@@ -82,7 +82,6 @@ impl<T: HttpTransport, A: AuthProvider> ModelsClient<T, A> {
#[cfg(test)]
mod tests {
use super::*;
use crate::provider::RequestCompression;
use crate::provider::RetryConfig;
use crate::provider::WireApi;
use async_trait::async_trait;
@@ -159,7 +158,6 @@ mod tests {
retry_5xx: true,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: Duration::from_secs(1),
}
}
+15 -3
View File
@@ -6,6 +6,7 @@ use crate::common::TextControls;
use crate::endpoint::streaming::StreamingClient;
use crate::error::ApiError;
use crate::provider::Provider;
use crate::provider::RequestCompression;
use crate::provider::WireApi;
use crate::requests::ResponsesRequest;
use crate::requests::ResponsesRequestBuilder;
@@ -33,6 +34,7 @@ pub struct ResponsesOptions {
pub conversation_id: Option<String>,
pub session_source: Option<SessionSource>,
pub extra_headers: HeaderMap,
pub request_compression: RequestCompression,
}
impl<T: HttpTransport, A: AuthProvider> ResponsesClient<T, A> {
@@ -55,8 +57,10 @@ impl<T: HttpTransport, A: AuthProvider> ResponsesClient<T, A> {
pub async fn stream_request(
&self,
request: ResponsesRequest,
request_compression: RequestCompression,
) -> Result<ResponseStream, ApiError> {
self.stream(request.body, request.headers).await
self.stream(request.body, request.headers, request_compression)
.await
}
#[instrument(level = "trace", skip_all, err)]
@@ -75,6 +79,7 @@ impl<T: HttpTransport, A: AuthProvider> ResponsesClient<T, A> {
conversation_id,
session_source,
extra_headers,
request_compression,
} = options;
let request = ResponsesRequestBuilder::new(model, &prompt.instructions, &prompt.input)
@@ -90,7 +95,7 @@ impl<T: HttpTransport, A: AuthProvider> ResponsesClient<T, A> {
.extra_headers(extra_headers)
.build(self.streaming.provider())?;
self.stream_request(request).await
self.stream_request(request, request_compression).await
}
fn path(&self) -> &'static str {
@@ -104,9 +109,16 @@ impl<T: HttpTransport, A: AuthProvider> ResponsesClient<T, A> {
&self,
body: Value,
extra_headers: HeaderMap,
request_compression: RequestCompression,
) -> Result<ResponseStream, ApiError> {
self.streaming
.stream(self.path(), body, extra_headers, spawn_response_stream)
.stream(
self.path(),
body,
extra_headers,
request_compression,
spawn_response_stream,
)
.await
}
}
+3 -4
View File
@@ -62,12 +62,11 @@ impl<T: HttpTransport, A: AuthProvider> StreamingClient<T, A> {
path: &str,
body: Value,
extra_headers: HeaderMap,
request_compression: RequestCompression,
spawner: fn(StreamResponse, Duration, Option<Arc<dyn SseTelemetry>>) -> ResponseStream,
) -> Result<ResponseStream, ApiError> {
let content_encoding =
matches!(self.provider.request_compression, RequestCompression::Zstd);
let encoded_body =
encode_body(&body, self.provider.request_compression).map_err(ApiError::Stream)?;
let content_encoding = matches!(request_compression, RequestCompression::Zstd);
let encoded_body = encode_body(&body, request_compression).map_err(ApiError::Stream)?;
let builder = || {
let mut req = self.provider.build_request(Method::POST, path);
+2 -2
View File
@@ -41,8 +41,9 @@ impl RetryConfig {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum RequestCompression {
#[default]
None,
Zstd,
}
@@ -59,7 +60,6 @@ pub struct Provider {
pub wire: WireApi,
pub headers: HeaderMap,
pub retry: RetryConfig,
pub request_compression: RequestCompression,
pub stream_idle_timeout: Duration,
}
+1 -2
View File
@@ -351,7 +351,7 @@ fn push_tool_call_message(messages: &mut Vec<Value>, tool_call: Value, reasoning
#[cfg(test)]
mod tests {
use super::*;
use crate::provider::RequestCompression;
use crate::provider::RetryConfig;
use crate::provider::WireApi;
use codex_protocol::models::FunctionCallOutputPayload;
@@ -375,7 +375,6 @@ mod tests {
retry_5xx: true,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: Duration::from_secs(1),
}
}
+1 -2
View File
@@ -172,7 +172,7 @@ fn attach_item_ids(payload_json: &mut Value, original_items: &[ResponseItem]) {
#[cfg(test)]
mod tests {
use super::*;
use crate::provider::RequestCompression;
use crate::provider::RetryConfig;
use crate::provider::WireApi;
use codex_protocol::protocol::SubAgentSource;
@@ -194,7 +194,6 @@ mod tests {
retry_5xx: true,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: Duration::from_secs(5),
}
}
+15 -7
View File
@@ -11,7 +11,6 @@ use codex_api::Provider;
use codex_api::ResponsesClient;
use codex_api::ResponsesOptions;
use codex_api::WireApi;
use codex_api::provider::RequestCompression;
use codex_client::HttpTransport;
use codex_client::Request;
use codex_client::Response;
@@ -133,7 +132,6 @@ fn provider(name: &str, wire: WireApi) -> Provider {
retry_5xx: false,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: Duration::from_millis(10),
}
}
@@ -203,7 +201,9 @@ async fn chat_client_uses_chat_completions_path_for_chat_wire() -> Result<()> {
let client = ChatClient::new(transport, provider("openai", WireApi::Chat), NoAuth);
let body = serde_json::json!({ "echo": true });
let _stream = client.stream(body, HeaderMap::new()).await?;
let _stream = client
.stream(body, HeaderMap::new(), Default::default())
.await?;
let requests = state.take_stream_requests();
assert_path_ends_with(&requests, "/chat/completions");
@@ -217,7 +217,9 @@ async fn chat_client_uses_responses_path_for_responses_wire() -> Result<()> {
let client = ChatClient::new(transport, provider("openai", WireApi::Responses), NoAuth);
let body = serde_json::json!({ "echo": true });
let _stream = client.stream(body, HeaderMap::new()).await?;
let _stream = client
.stream(body, HeaderMap::new(), Default::default())
.await?;
let requests = state.take_stream_requests();
assert_path_ends_with(&requests, "/responses");
@@ -231,7 +233,9 @@ async fn responses_client_uses_responses_path_for_responses_wire() -> Result<()>
let client = ResponsesClient::new(transport, provider("openai", WireApi::Responses), NoAuth);
let body = serde_json::json!({ "echo": true });
let _stream = client.stream(body, HeaderMap::new()).await?;
let _stream = client
.stream(body, HeaderMap::new(), Default::default())
.await?;
let requests = state.take_stream_requests();
assert_path_ends_with(&requests, "/responses");
@@ -245,7 +249,9 @@ async fn responses_client_uses_chat_path_for_chat_wire() -> Result<()> {
let client = ResponsesClient::new(transport, provider("openai", WireApi::Chat), NoAuth);
let body = serde_json::json!({ "echo": true });
let _stream = client.stream(body, HeaderMap::new()).await?;
let _stream = client
.stream(body, HeaderMap::new(), Default::default())
.await?;
let requests = state.take_stream_requests();
assert_path_ends_with(&requests, "/chat/completions");
@@ -260,7 +266,9 @@ async fn streaming_client_adds_auth_headers() -> Result<()> {
let client = ResponsesClient::new(transport, provider("openai", WireApi::Responses), auth);
let body = serde_json::json!({ "model": "gpt-test" });
let _stream = client.stream(body, HeaderMap::new()).await?;
let _stream = client
.stream(body, HeaderMap::new(), Default::default())
.await?;
let requests = state.take_stream_requests();
assert_eq!(requests.len(), 1);
@@ -1,7 +1,6 @@
use codex_api::AuthProvider;
use codex_api::ModelsClient;
use codex_api::provider::Provider;
use codex_api::provider::RequestCompression;
use codex_api::provider::RetryConfig;
use codex_api::provider::WireApi;
use codex_client::ReqwestTransport;
@@ -43,7 +42,6 @@ fn provider(base_url: &str) -> Provider {
retry_5xx: true,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: std::time::Duration::from_secs(1),
}
}
+10 -4
View File
@@ -9,7 +9,6 @@ use codex_api::Provider;
use codex_api::ResponseEvent;
use codex_api::ResponsesClient;
use codex_api::WireApi;
use codex_api::provider::RequestCompression;
use codex_client::HttpTransport;
use codex_client::Request;
use codex_client::Response;
@@ -75,7 +74,6 @@ fn provider(name: &str, wire: WireApi) -> Provider {
retry_5xx: false,
retry_transport: true,
},
request_compression: RequestCompression::None,
stream_idle_timeout: Duration::from_millis(50),
}
}
@@ -126,7 +124,11 @@ async fn responses_stream_parses_items_and_completed_end_to_end() -> Result<()>
let client = ResponsesClient::new(transport, provider("openai", WireApi::Responses), NoAuth);
let mut stream = client
.stream(serde_json::json!({"echo": true}), HeaderMap::new())
.stream(
serde_json::json!({"echo": true}),
HeaderMap::new(),
Default::default(),
)
.await?;
let mut events = Vec::new();
@@ -191,7 +193,11 @@ async fn responses_stream_aggregates_output_text_deltas() -> Result<()> {
let client = ResponsesClient::new(transport, provider("openai", WireApi::Responses), NoAuth);
let stream = client
.stream(serde_json::json!({"echo": true}), HeaderMap::new())
.stream(
serde_json::json!({"echo": true}),
HeaderMap::new(),
Default::default(),
)
.await?;
let mut stream = stream.aggregate();