feat: support custom HTTP headers for model providers (#1473)

This adds support for two new model provider config options:

- `http_headers` for hardcoded (key, value) pairs
- `env_http_headers` for headers whose values should be read from
environment variables

This also updates the built-in `openai` provider to use this feature to
set the following headers:

- `originator` => `codex_cli_rs`
- `version` => [CLI version]
- `OpenAI-Organization` => `OPENAI_ORGANIZATION` env var
- `OpenAI-Project` => `OPENAI_PROJECT` env var

for consistency with the TypeScript implementation:


bd5a9e8ba9/codex-cli/src/utils/agent/agent-loop.ts (L321-L329)

While here, this also consolidates some logic that was duplicated across
`client.rs` and `chat_completions.rs` by introducing
`ModelProviderInfo.create_request_builder()`.

Resolves https://github.com/openai/codex/discussions/1152
This commit is contained in:
Michael Bolin
2025-07-07 13:09:16 -07:00
committed by GitHub
parent bd5a9e8ba9
commit c221eab0b5
7 changed files with 147 additions and 27 deletions

View File

@@ -114,22 +114,18 @@ pub(crate) async fn stream_chat_completions(
"tools": tools_json,
});
let url = provider.get_full_url();
debug!(
"POST to {url}: {}",
"POST to {}: {}",
provider.get_full_url(),
serde_json::to_string_pretty(&payload).unwrap_or_default()
);
let api_key = provider.api_key()?;
let mut attempt = 0;
loop {
attempt += 1;
let mut req_builder = client.post(&url);
if let Some(api_key) = &api_key {
req_builder = req_builder.bearer_auth(api_key.clone());
}
let req_builder = provider.create_request_builder(client)?;
let res = req_builder
.header(reqwest::header::ACCEPT, "text/event-stream")
.json(&payload)