## What changed
- Probe the configured Responses inference endpoint with Codex's route-aware HTTP client, including configured proxy and custom CA behavior.
- Classify TLS, proxy authentication, proxy configuration, resolution, and timeout failures into actionable diagnostics.
- Report privacy-safe macOS system proxy state and suggest enabling `respect_system_proxy` when a configured proxy is otherwise unused.
- Preserve system-root fallback when a custom CA is invalid, and account for provider-specific API key configuration when selecting the probe route.
## Testing
- Cover inference endpoint selection, invalid custom CA fallback, proxy authentication failures, TLS classification, and macOS proxy reporting.
GitOrigin-RevId: c30a3ca5a332119e2b2f8c65341ef9b2251a28a2
## Why
Local MCP requests can fail when the platform TLS backend cannot negotiate a
protocol version with an HTTPS endpoint.
## What changed
- Retry replayable local MCP requests once with rustls after a recognized TLS
protocol-version negotiation failure. Keep certificate, timeout, and unrelated
connection failures on the existing error path.
- Remember successful fallback per HTTPS origin and outbound route, while keeping
the platform TLS backend as the default for other destinations.
- Share the fallback-enabled client across local MCP resolution, CLI login, and
OAuth discovery while preserving remote environment HTTP clients.
## Testing
Added coverage for platform-specific error detection, request replay, cached
fallback reuse and isolation, non-replayable requests, redirects, and remote MCP
client selection.
GitOrigin-RevId: 39a2d96fdb2ea0e51df14f652ba2a953d24e69a1
## What changed
- Classify HTTP connection failures separately from other network errors without exposing request URLs.
- For sampling requests, retry connection failures with exponential delays from 5 to 60 seconds and show a `Reconnecting... waiting for network` stream error.
- Preserve the normal stream retry budget while waiting for the provider to become reachable. Keep the existing bounded retry behavior for other retryable errors.
## Testing
- Verify connection errors are classified without leaking URL contents.
- Verify a turn recovers after its provider becomes reachable and still applies the configured retry limit to a subsequent incomplete stream.
GitOrigin-RevId: 646553290c865a1332abd30c4a64ed9266bbfc6f
## What changed
- Let `HttpClientFactory` carry additional ChatGPT cookies and share their store across cloned factories.
- Attach configured cookies when route-aware clients or explicitly opted-in clients enable the ChatGPT cookie store.
- Combine configured cookies with the current path-scoped Cloudflare cookies only for HTTPS ChatGPT hosts, while preserving sensitive-header metadata.
## Testing
- Cover cookie merging, path-scoped Cloudflare updates, host and scheme restrictions, sensitive values, and factory clone/equality behavior.
GitOrigin-RevId: 5baf745859e14db739fd62ab931720dbe90c04e0
## Why
TUI update checks and local OSS provider detection constructed their own HTTP
clients instead of using Codex's shared client behavior.
## What changed
- Route update requests through the configured route-aware client pool while
retaining the existing default headers and custom CA fallback.
- Probe the hardcoded LM Studio and Ollama loopback endpoints with a shared
direct client and a per-request timeout.
- Limit the legacy invalid-custom-CA fallback to the default routing policy so
system-proxy routing still reports certificate configuration errors.
## Testing
Add coverage for local provider probes with invalid `CODEX_CA_CERTIFICATE` and
`SSL_CERT_FILE` values, and for custom CA fallback under both routing policies.
GitOrigin-RevId: b5c230b61e8964b3f1af3395052361ff716d6ce1
## What changed
- Store a request-logging-disabled `RouteAwareClientPool` in session services and use it for file creation, blob upload, and finalization requests.
- Preserve the existing system-root fallback for transport-default proxy routes, and emit a warning event when that fallback is used.
- Remove the direct `reqwest` dependency from `codex-api` now that uploads use the shared HTTP abstraction.
## Testing
- Add coverage for completing multiple uploads through a shared client pool.
GitOrigin-RevId: 01842415cad2d349a6bd3869abb3332e8110ebce
## What changed
- Add `RouteAwareRequestBuilder::body_stream` for sending fallible byte streams without exposing the underlying HTTP client body type.
- Expose request- and body-error classification on `RouteAwareRequestError`.
- Add `RouteAwareRequestError::without_url` so callers can remove credential-bearing URLs, such as signed upload URLs, from transport errors.
## Testing
- Verify streamed request bytes reach the server.
- Verify URL secrets are absent after stripping a transport error's URL.
GitOrigin-RevId: 6a100f56a9aa7d79d9b6dd0f103135f5f2060617
## Why
Noise environment registry requests need to follow the exec server's effective
outbound proxy policy without exposing registry URLs or response headers in HTTP
diagnostics.
## What changed
- Build the registry client from the supplied `HttpClientFactory` and use a
route-aware API client with redirects and request logging disabled.
- Defer construction of the Noise connection provider until the outbound HTTP
policy is available.
- Map route-aware request failures into registry errors while retaining timeout
detection across response body reads.
## Testing
Add coverage for system-proxy routing, sensitive registry metadata redaction,
stalled response-body timeouts, and prepared Noise configuration validation.
GitOrigin-RevId: d312dfe037f72732085bf38109af44df76ed0b53
## Why
Delegated HTTP requests need to honor the same outbound proxy policy as the
Codex process that starts the exec server.
## What changed
- Pass the configured `HttpClientFactory` through local and remote exec-server
startup and use route-aware client pools for delegated HTTP and local MCP
requests.
- Preserve per-request timeouts and follow-or-stop redirect behavior while
keeping request URLs and sensitive response headers out of diagnostics.
## Testing
- Cover configured system-proxy routing across the exec-server transport.
- Cover both redirect policies and verify that success and failure logs do not
expose request or response secrets.
GitOrigin-RevId: 4af6aec1d265c4db62dfcb6e1fb076fb31736137
## Why
With system-proxy-aware routing, `RouteAwareClientPool` handles redirects itself so each hop can resolve its own route. That manual path must also respect clients configured not to follow redirects.
## What changed
- Add no-redirect constructors for standard and ChatGPT Cloudflare-cookie route-aware client pools.
- Skip manual redirect handling when the underlying client builder has redirects disabled, returning the redirect response to the caller.
## Testing
- Cover both outbound proxy policies and verify that a no-redirect pool returns the initial `302 Found` response after one request.
GitOrigin-RevId: 7eec73f21f506a46e5d4b82f425ddbc9761ca61c
## What changed
- Use the configured route-aware HTTP client pool for LM Studio server requests.
- Add connection-timeout support to `HttpClientBuilder` and route-aware pools, and keep LM Studio's five-second limit scoped to connection establishment.
- Verify that LM Studio accepts a response that arrives after the connection timeout has elapsed once the connection is established.
GitOrigin-RevId: c4300f4b5d37c4418822783ab09cb50d506ee423
## What changed
- Document `codex-http-client` as the owner of direct `reqwest` integration and shared outbound request policies.
- Explain how to select outbound proxy policies, retain clients for connection reuse, and use route-aware pooling for multi-URL and redirecting traffic.
- Add examples for constructing policy-aware clients and transports, plus guidance for direct routing and sensitive request data.
GitOrigin-RevId: 892db4be92af5ec42eced8d7dec4651c9f464689
## Why
ChatGPT token refresh requests need to follow the same configured routing policy as other authentication traffic, including environments that use the system proxy.
## What changed
- Require an `AuthRouteConfig` throughout login, logout, token refresh, personal access token, and agent identity flows.
- Build auth HTTP clients directly from that configuration instead of falling back to a default HTTP client when routing configuration is absent.
## Testing
- Add an integration test that refreshes a token through a cached system-proxy route and verifies the proxy receives the expected request.
GitOrigin-RevId: 7d54ab3219939a49921c51faf08cd4c2eabca51c
## What changed
- Add `HttpClientBuilder` for configuring default headers, redirects, the
Cloudflare cookie store, and request diagnostics without exposing the
underlying transport.
- Provide factory-backed construction for fixed destinations that respects
outbound proxy policy, alongside explicit direct and legacy
transport-default construction paths.
- Preserve the request-logging setting in `ReqwestTransport`, so disabling
diagnostics also suppresses transport-level URL and request-body traces.
- Add `HEAD`, `DELETE`, and query-parameter helpers to the shared client
wrappers.
## Testing
- Verify builder configuration survives policy-aware construction and custom
CA fallback.
- Verify disabled request logging omits request URLs and bodies from transport
traces.
GitOrigin-RevId: 529c33abefeb88f38ff9a0ead374d29fcc872e6a
## Why
Remote plugin requests did not use Codex's effective outbound proxy policy, so
they could bypass configured system proxy and PAC routing.
## What changed
- Route remote plugin catalog, mutation, sharing, upload, and bundle download
requests through the configured route-aware HTTP client.
- Select routes using the complete request URL, including encoded query
parameters and backend-provided signed upload or download URLs.
- Preserve standard Codex headers and suppress diagnostics for URLs or headers
that may contain credentials.
## Testing
Add coverage for route selection of catalog queries, workspace plugin uploads,
and backend-provided bundle download URLs.
GitOrigin-RevId: 106936659e21decf145b6ab4d4be84992e386861
## What changed
- Add end-to-end coverage that exact-URL system proxy decisions select the expected route, including when a redirect switches routes.
- Verify redirects strip credential headers across origins while retaining them for the same origin and route.
- Check that redirect chains emit only the final request outcome, omit sensitive redirect details from logs, and honor disabled request logging.
- Share local HTTP listener helpers across the outbound proxy tests.
GitOrigin-RevId: afd1640e1910442d71fa1dc77b20b4fb1a6f1b6a
## What changed
- Cover redirect method and body handling, `Referer` behavior, and credential
stripping across origins.
- Exercise request deadlines across route selection and redirect hops, along
with redirect limits and unsupported schemes.
- Verify that disabling pool request logging does not expose request or
response data.
GitOrigin-RevId: a683956c468b45304d0bdc25081f5f4e03836ccd
## Why
Route-aware clients select a direct or proxy route from the complete request
URL. Letting `reqwest` follow redirects internally reuses the client chosen for
the original URL, so the redirect destination cannot receive its own PAC or
system proxy decision.
## What changed
- Follow redirects through `RouteAwareClientPool` when respecting the system
proxy, resolving and caching a route for every hop.
- Preserve standard redirect method and body behavior, enforce one timeout
across the request chain, and cap redirects at 10 hops.
- Strip origin-sensitive credentials and stale proxy authorization when the
destination or selected route changes, and apply safe `Referer` handling.
- Log one final request outcome instead of intermediate redirect responses.
## Testing
Added an integration test covering a redirect from a direct route to a proxy
route, credential handling, and final-outcome logging.
GitOrigin-RevId: e5cb2cc962e99d33df61ef649465e956b92279bb
## What changed
- Add an execution path that injects trace headers and sends a request without
logging its result.
- Extract response and error logging into reusable helpers while preserving the
existing behavior of `HttpClient::execute`.
GitOrigin-RevId: 3feebe3da041dd08f5033dd319233d8afe9054ec
## Why
PAC and system-proxy resolution can select a different outbound route for each
request URL. Request creation and route selection must use the same URL while
still allowing transport clients to be reused.
## What changed
- Add `RouteAwareClientPool` and a request builder that resolve the outbound
proxy route when sending each request.
- Reuse HTTP clients by resolved route, with a bounded cache of 16 routes.
- Preserve request tracing, optional diagnostic logging, custom CA settings,
Cloudflare cookies, and default transport redirect behavior.
- Export route-aware response and error types, including status, timeout, and
connection-error helpers.
## Testing
Add tests for exact URL routing, client reuse and eviction, default redirects,
and redaction of URL secrets from debug output.
GitOrigin-RevId: a1688b64305a0bb276c371df63a039ccbe821b76
## Why
System proxy discovery can block, and delegating fallback to each transport can repeat discovery or apply inconsistent environment proxy behavior.
## What changed
- Resolve unavailable system proxy decisions to an explicit environment proxy or direct route, including `NO_PROXY` settings and WebSocket-specific fallbacks.
- Add asynchronous system proxy resolution that uses cached decisions first and serializes blocking platform lookups on Windows and macOS.
- Preserve `NO_PROXY` handling for WebSocket connections, including HTTP and HTTPS proxies, and hash proxy cache keys on every platform.
## Testing
- Add coverage for explicit environment fallback, cached asynchronous resolution, and proxied or bypassed WebSocket connections.
GitOrigin-RevId: 3b7cf170dcfe639eec53c3c1514f92bfcf13e7e9
## Why
Login already honors `respect_system_proxy`, but several login-owned
auth flows still construct and pass around raw `reqwest::Client` values.
That keeps those request paths coupled to the underlying transport and
leaves `codex-login` on the temporary direct-`reqwest` allowlist
introduced by #31431.
Auth endpoints also have a stricter logging boundary than ordinary API
requests: custom issuer URLs and response headers may contain
credentials. Moving these requests behind the shared HTTP abstraction
must preserve that boundary while retaining route-aware proxy and
custom-CA behavior.
This is a bounded login migration. The separate Agent Identity and
shared default-client compatibility migrations remain follow-up work.
## What changed
- Add `HttpClientFactory::build_client` to construct the shared
`HttpClient` abstraction for a resolved destination and route class.
- Add a route-aware construction path that suppresses request URL,
response-header, and transport-error diagnostics for sensitive auth
endpoints.
- Route device-code user-code/polling requests, OAuth authorization-code
exchange, and API-key token exchange through `HttpClient`.
- Build the revoke timeout test client through the same factory API.
- Use the transport-neutral `http::StatusCode` in the migrated
device-code flow.
- Add an end-to-end log-capture regression test covering successful
responses and transport failures after `RequestBuilder` transformations.
## Review guidance
The request behavior is intended to be unchanged: each issuer/token
endpoint selects the same auth route, including the existing system/PAC
proxy and custom-CA handling, and raw auth clients still omit Codex
default headers. The intentional logging change is limited to raw auth
requests, whose URL userinfo, query credentials, response headers, and
transport errors must not cross the auth redaction boundary.
This PR deliberately does **not** remove `codex-login` from #31431's
allowlist. The remaining direct `reqwest` surface belongs primarily to:
- Agent Identity APIs that still accept `reqwest::Client`.
- Exported default-client compatibility helpers used by other workspace
crates.
- A small number of tests and concrete error/header types.
## Testing
- `cargo check -p codex-http-client -p codex-login --tests`
- `just test -p codex-http-client` (41 tests)
- `just test -p codex-login` (155 tests)
- `just bazel-lock-check`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31637).
* #31837
* #31828
* #31825
* #31821
* __->__ #31637
## Why
#31335 lets HTTP callers obtain proxy-aware clients from
`HttpClientFactory`, but a non-HTTP transport such as WebSockets also
needs two pieces of policy owned by `codex-http-client`: a concrete
route decision for its destination and the same custom-CA-aware rustls
trust configuration used by HTTPS.
Keeping these prerequisites in the shared abstraction means the
dependent Responses WebSocket change (#31441) cannot independently
reinterpret `features.respect_system_proxy`, PAC results, or enterprise
CA settings.
## What changed
- Add a redaction-safe `OutboundProxyRoute` with explicit
transport-default, direct, and concrete-proxy outcomes.
- Add `HttpClientFactory::resolve_proxy_route()` so transports can
resolve a destination through the already-selected outbound proxy
policy.
- Resolve `ws://` and `wss://` URLs through their HTTP equivalents so
system and PAC rules apply consistently.
- Add an always-returned rustls config builder that starts from native
roots and layers in any configured Codex custom CA bundle. The existing
optional builder remains available to callers that can delegate the
default configuration to their transport.
- Continue redacting proxy URLs from `Debug` output because they may
contain credentials.
## Review guide
1. `http-client/src/outbound_proxy.rs` defines the transport-neutral
route result and WebSocket URL normalization.
2. `http-client/src/custom_ca.rs` factors the native-root/custom-CA
construction so callers that perform TLS themselves can always obtain a
config.
3. `http-client/src/outbound_proxy_tests.rs` verifies WebSocket
normalization and legacy transport-default behavior.
## Test plan
- `just test -p codex-http-client outbound_proxy`
- `just test -p codex-http-client custom_ca`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31342).
* #31431
* #31363
* #31362
* #31361
* #31442
* #31441
* __->__ #31342
## Why
`features.respect_system_proxy` already routes authentication traffic
through the OS proxy APIs, but it does not affect the primary inference
path. That leaves users behind OS-managed proxies unable to send normal
Responses API requests even after login succeeds.
This PR is the first product-path migration onto the route-aware
transport introduced in #31323 and refined in #31331. It also
establishes the construction pattern for later migrations: the effective
feature state is resolved once into a required HTTP client factory
rather than represented by an optional per-call setting.
The scope remains limited to the two HTTP Responses endpoints;
WebSockets, model discovery, memories, realtime, and file uploads remain
follow-up migrations.
## What changed
- Replace the optional proxy marker with an explicit
`OutboundProxyPolicy::{ReqwestDefault, RespectSystemProxy}` and a
required `HttpClientFactory`. The policy has no default, and the
lower-level route-aware reqwest builder is now private.
- Have `Config` construct the factory from the effective feature state
and require every `ModelClient` constructor to receive it. There is no
optional setter or implicit `None` fallback.
- Build HTTP clients for `/responses` and `/responses/compact` with
`ClientRouteClass::Api`, using the complete destination URL so PAC rules
can make URL-specific decisions.
- Layer route-aware selection onto Codex's existing default headers,
Cloudflare cookie store, custom CA handling, and sandbox no-proxy
behavior.
- Add an integration test that loads `features.respect_system_proxy`
through `config.toml`, creates a real Codex session, and verifies that
both a normal Responses turn and remote compaction reach an isolated
local proxy.
## Review guide
1. `http-client/src/outbound_proxy.rs` defines the mandatory
policy/factory boundary and keeps route resolution private.
2. `core/src/config/mod.rs`, `core/src/session/session.rs`, and
`core/src/client.rs` show the compile-time invariant: effective config
creates the factory, and `ModelClient` cannot be constructed without
one.
3. `login/src/auth/default_client.rs` preserves existing default-client
behavior while accepting the required factory for migrated routes.
4. `core/src/client.rs` switches only streaming Responses and remote
compaction HTTP transports to the API route class.
5. `core/tests/suite/responses_api_system_proxy.rs` is the behavioral
regression boundary. Its Linux subprocess deliberately sets the CGI
marker that disables reqwest's implicit environment-proxy handling, so
the test fails if session wiring or either Responses call site falls
back to the default client.
## Test plan
- `cargo check --tests -p codex-http-client -p codex-login -p
codex-core`
- `just test -p codex-login`
- `just test -p codex-core
respect_system_proxy_feature_resolves_enabled`
- Existing `compact_uses_bearer_after_agent_identity_session_fallback`
coverage passes with the new transport construction.
- New Linux integration coverage:
`responses_and_compact_use_enabled_system_proxy`
- `just bazel-lock-check`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31335).
* #31342
* __->__ #31335
## Why
Codex-owned HTTP construction currently lives in `codex-client`
alongside higher-level retry, SSE, and request-telemetry policy. That
makes it difficult to apply shared network behavior consistently across
crates, particularly system proxy/PAC resolution, custom CA handling,
and the ChatGPT Cloudflare cookie policy. It also leaves no clear crate
boundary for migrating direct `reqwest` usage behind a single Codex
abstraction.
This change establishes that low-level ownership boundary without
changing request behavior. It builds on the system proxy support
introduced in #26706, #26707, #26708, and #26709.
## What changed
- Added `codex-rs/http-client` as the `codex-http-client` crate.
- Moved request/response types, the concrete `reqwest` transport, custom
CA handling, Cloudflare cookie policy, and macOS/Windows proxy
resolution into the new crate.
- Kept retry, SSE, and request-telemetry policy in `codex-client`.
- Re-exported the moved API from `codex-client`, including compatibility
aliases for `CodexHttpClient` and `CodexRequestBuilder`, so existing
consumers do not change in this PR.
- Moved the existing proxy and custom-CA tests with their
implementation.
## Scope boundary
This PR deliberately stops at the crate extraction. Stacked follow-up
#31331 migrates downstream imports from `codex-client` to
`codex-http-client`, keeping this change focused on ownership and
compatibility rather than mixing in repository-wide call-site churn.
## Review guide
GitHub reports 30 changed files, of which 17 are detected renames. A
useful review order is:
1. Review the new boundary in `codex-rs/http-client/Cargo.toml` and
`codex-rs/http-client/src/lib.rs`.
2. Review `codex-rs/codex-client/Cargo.toml` and
`codex-rs/codex-client/src/lib.rs` for what remains in the higher-level
crate and how compatibility is preserved.
3. Treat the renamed implementation and test files as moves. Their
meaningful edits are limited to crate paths and normalizing the new
crate's type names to `HttpClient` and `RequestBuilder`.
4. Review `codex-rs/Cargo.toml`, `codex-rs/Cargo.lock`, and the two
`BUILD.bazel` files as mechanical workspace integration.
## Test plan
- `just test -p codex-http-client -p codex-client` (38 tests)
- Compile-checked the unchanged `codex-api`, `codex-backend-client`,
`codex-cloud-tasks`, `codex-exec-server`, `codex-login`, and
`codex-model-provider` consumers against the compatibility re-exports.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31323).
* #31331
* __->__ #31323