Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codex-rs/codex-api/src/api_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ pub fn map_api_error(err: ApiError) -> CodexErr {
status: http::StatusCode::INTERNAL_SERVER_ERROR,
request_id: None,
}),
TransportError::Timeout => CodexErr::Timeout,
TransportError::Timeout => CodexErr::RequestTimeout,
TransportError::Network(msg) | TransportError::Build(msg) => {
CodexErr::Stream(msg, None)
}
Expand Down
15 changes: 13 additions & 2 deletions codex-rs/codex-api/src/endpoint/compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use http::Method;
use serde::Deserialize;
use serde_json::to_value;
use std::sync::Arc;
use std::time::Duration;

pub struct CompactClient<T: HttpTransport> {
session: EndpointSession<T>,
Expand All @@ -37,10 +38,19 @@ impl<T: HttpTransport> CompactClient<T> {
&self,
body: serde_json::Value,
extra_headers: HeaderMap,
request_timeout: Duration,
) -> Result<Vec<ResponseItem>, ApiError> {
let resp = self
.session
.execute(Method::POST, Self::path(), extra_headers, Some(body))
.execute_with(
Method::POST,
Self::path(),
extra_headers,
Some(body),
|req| {
req.timeout = Some(request_timeout);
},
)
.await?;
let parsed: CompactHistoryResponse =
serde_json::from_slice(&resp.body).map_err(|e| ApiError::Stream(e.to_string()))?;
Expand All @@ -51,10 +61,11 @@ impl<T: HttpTransport> CompactClient<T> {
&self,
input: &CompactionInput<'_>,
extra_headers: HeaderMap,
request_timeout: Duration,
) -> Result<Vec<ResponseItem>, ApiError> {
let body = to_value(input)
.map_err(|e| ApiError::Stream(format!("failed to encode compaction input: {e}")))?;
self.compact(body, extra_headers).await
self.compact(body, extra_headers, request_timeout).await
}
}

Expand Down
9 changes: 8 additions & 1 deletion codex-rs/core/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ const X_CODEX_WS_STREAM_REQUEST_START_MS_CLIENT_METADATA_KEY: &str =
const RESPONSES_WEBSOCKETS_V2_BETA_HEADER_VALUE: &str = "responses_websockets=2026-02-06";
const RESPONSES_ENDPOINT: &str = "/responses";
const RESPONSES_COMPACT_ENDPOINT: &str = "/responses/compact";
// `/responses/compact` is unary, so the timeout covers the full response rather than one idle
// period between stream events.
const COMPACT_REQUEST_TIMEOUT_IDLE_MULTIPLIER: u32 = 4;
const MEMORIES_SUMMARIZE_ENDPOINT: &str = "/memories/trace_summarize";
#[cfg(test)]
pub(crate) const WEBSOCKET_CONNECT_TIMEOUT: Duration =
Expand Down Expand Up @@ -502,12 +505,16 @@ impl ModelClient {
if let Some(header_value) = self.generate_attestation_header_for().await {
extra_headers.insert(X_OAI_ATTESTATION_HEADER, header_value);
}
let compact_request_timeout = client_setup
.api_provider
.stream_idle_timeout
.saturating_mul(COMPACT_REQUEST_TIMEOUT_IDLE_MULTIPLIER);
let client =
ApiCompactClient::new(transport, client_setup.api_provider, client_setup.api_auth)
.with_telemetry(Some(request_telemetry));
let trace_attempt = compaction_trace.start_attempt(&payload);
let result = client
.compact_input(&payload, extra_headers)
.compact_input(&payload, extra_headers, compact_request_timeout)
Comment thread
jif-oai marked this conversation as resolved.
.await
.map_err(map_api_error);
trace_attempt.record_result(result.as_deref());
Expand Down
3 changes: 3 additions & 0 deletions codex-rs/protocol/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ pub enum CodexErr {
/// Returned by run_command_stream when the spawned child process timed out (10s).
#[error("timeout waiting for child process to exit")]
Timeout,
#[error("request timed out")]
RequestTimeout,
/// Returned by run_command_stream when the child could not be spawned (its stdout/stderr pipes
/// could not be captured). Analogous to the previous `CodexError::Spawn` variant.
#[error("spawn failed: child stdout/stderr not captured")]
Expand Down Expand Up @@ -192,6 +194,7 @@ impl CodexErr {
| CodexErr::CyberPolicy { .. } => false,
CodexErr::Stream(..)
| CodexErr::Timeout
| CodexErr::RequestTimeout
| CodexErr::UnexpectedStatus(_)
| CodexErr::ResponseStreamFailed(_)
| CodexErr::ConnectionFailed(_)
Expand Down
Loading