Skip to content

Commit ce366d6

Browse files
committed
feat: add secret_key option to model provider definition
1 parent da82153 commit ce366d6

File tree

9 files changed

+39
-8
lines changed

9 files changed

+39
-8
lines changed

codex-rs/core/src/client.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,7 @@ mod tests {
10931093
base_url: Some("https://test.com".to_string()),
10941094
env_key: Some("TEST_API_KEY".to_string()),
10951095
env_key_instructions: None,
1096+
secret_key: None,
10961097
wire_api: WireApi::Responses,
10971098
query_params: None,
10981099
http_headers: None,
@@ -1156,6 +1157,7 @@ mod tests {
11561157
base_url: Some("https://test.com".to_string()),
11571158
env_key: Some("TEST_API_KEY".to_string()),
11581159
env_key_instructions: None,
1160+
secret_key: None,
11591161
wire_api: WireApi::Responses,
11601162
query_params: None,
11611163
http_headers: None,
@@ -1192,6 +1194,7 @@ mod tests {
11921194
base_url: Some("https://test.com".to_string()),
11931195
env_key: Some("TEST_API_KEY".to_string()),
11941196
env_key_instructions: None,
1197+
secret_key: None,
11951198
wire_api: WireApi::Responses,
11961199
query_params: None,
11971200
http_headers: None,
@@ -1230,6 +1233,7 @@ mod tests {
12301233
base_url: Some("https://test.com".to_string()),
12311234
env_key: Some("TEST_API_KEY".to_string()),
12321235
env_key_instructions: None,
1236+
secret_key: None,
12331237
wire_api: WireApi::Responses,
12341238
query_params: None,
12351239
http_headers: None,
@@ -1264,6 +1268,7 @@ mod tests {
12641268
base_url: Some("https://test.com".to_string()),
12651269
env_key: Some("TEST_API_KEY".to_string()),
12661270
env_key_instructions: None,
1271+
secret_key: None,
12671272
wire_api: WireApi::Responses,
12681273
query_params: None,
12691274
http_headers: None,
@@ -1367,6 +1372,7 @@ mod tests {
13671372
base_url: Some("https://test.com".to_string()),
13681373
env_key: Some("TEST_API_KEY".to_string()),
13691374
env_key_instructions: None,
1375+
secret_key: None,
13701376
wire_api: WireApi::Responses,
13711377
query_params: None,
13721378
http_headers: None,

codex-rs/core/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,6 +2801,7 @@ model_verbosity = "high"
28012801
env_key: Some("OPENAI_API_KEY".to_string()),
28022802
wire_api: crate::WireApi::Chat,
28032803
env_key_instructions: None,
2804+
secret_key: None,
28042805
query_params: None,
28052806
http_headers: None,
28062807
env_http_headers: None,

codex-rs/core/src/model_provider_info.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ pub struct ModelProviderInfo {
4949
/// Environment variable that stores the user's API key for this provider.
5050
pub env_key: Option<String>,
5151

52+
/// The value of the key to use with the provider. Use of this config is
53+
/// discouraged in favor of `env_key` for security reasons, but this may
54+
/// be necessary when using this programmatically.
55+
pub secret_key: Option<String>,
56+
5257
/// Optional instructions to help the user get a valid value for the
5358
/// variable and set it.
5459
pub env_key_instructions: Option<String>,
@@ -102,14 +107,18 @@ impl ModelProviderInfo {
102107
client: &'a reqwest::Client,
103108
auth: &Option<CodexAuth>,
104109
) -> crate::error::Result<reqwest::RequestBuilder> {
105-
let effective_auth = match self.api_key() {
106-
Ok(Some(key)) => Some(CodexAuth::from_api_key(&key)),
107-
Ok(None) => auth.clone(),
108-
Err(err) => {
109-
if auth.is_some() {
110-
auth.clone()
111-
} else {
112-
return Err(err);
110+
let effective_auth = if let Some(secret_key) = &self.secret_key {
111+
Some(CodexAuth::from_api_key(secret_key))
112+
} else {
113+
match self.api_key() {
114+
Ok(Some(key)) => Some(CodexAuth::from_api_key(&key)),
115+
Ok(None) => auth.clone(),
116+
Err(err) => {
117+
if auth.is_some() {
118+
auth.clone()
119+
} else {
120+
return Err(err);
121+
}
113122
}
114123
}
115124
};
@@ -274,6 +283,7 @@ pub fn built_in_model_providers() -> HashMap<String, ModelProviderInfo> {
274283
.filter(|v| !v.trim().is_empty()),
275284
env_key: None,
276285
env_key_instructions: None,
286+
secret_key: None,
277287
wire_api: WireApi::Responses,
278288
query_params: None,
279289
http_headers: Some(
@@ -333,6 +343,7 @@ pub fn create_oss_provider_with_base_url(base_url: &str) -> ModelProviderInfo {
333343
base_url: Some(base_url.into()),
334344
env_key: None,
335345
env_key_instructions: None,
346+
secret_key: None,
336347
wire_api: WireApi::Chat,
337348
query_params: None,
338349
http_headers: None,
@@ -372,6 +383,7 @@ base_url = "http://localhost:11434/v1"
372383
base_url: Some("http://localhost:11434/v1".into()),
373384
env_key: None,
374385
env_key_instructions: None,
386+
secret_key: None,
375387
wire_api: WireApi::Chat,
376388
query_params: None,
377389
http_headers: None,
@@ -399,6 +411,7 @@ query_params = { api-version = "2025-04-01-preview" }
399411
base_url: Some("https://xxxxx.openai.azure.com/openai".into()),
400412
env_key: Some("AZURE_OPENAI_API_KEY".into()),
401413
env_key_instructions: None,
414+
secret_key: None,
402415
wire_api: WireApi::Chat,
403416
query_params: Some(maplit::hashmap! {
404417
"api-version".to_string() => "2025-04-01-preview".to_string(),
@@ -429,6 +442,7 @@ env_http_headers = { "X-Example-Env-Header" = "EXAMPLE_ENV_VAR" }
429442
base_url: Some("https://example.com".into()),
430443
env_key: Some("API_KEY".into()),
431444
env_key_instructions: None,
445+
secret_key: None,
432446
wire_api: WireApi::Chat,
433447
query_params: None,
434448
http_headers: Some(maplit::hashmap! {
@@ -455,6 +469,7 @@ env_http_headers = { "X-Example-Env-Header" = "EXAMPLE_ENV_VAR" }
455469
base_url: Some(base_url.into()),
456470
env_key: None,
457471
env_key_instructions: None,
472+
secret_key: None,
458473
wire_api: WireApi::Responses,
459474
query_params: None,
460475
http_headers: None,
@@ -487,6 +502,7 @@ env_http_headers = { "X-Example-Env-Header" = "EXAMPLE_ENV_VAR" }
487502
base_url: Some("https://example.com".into()),
488503
env_key: None,
489504
env_key_instructions: None,
505+
secret_key: None,
490506
wire_api: WireApi::Responses,
491507
query_params: None,
492508
http_headers: None,

codex-rs/core/tests/chat_completions_payload.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ async fn run_request(input: Vec<ResponseItem>) -> Value {
5050
base_url: Some(format!("{}/v1", server.uri())),
5151
env_key: None,
5252
env_key_instructions: None,
53+
secret_key: None,
5354
wire_api: WireApi::Chat,
5455
query_params: None,
5556
http_headers: None,

codex-rs/core/tests/chat_completions_sse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ async fn run_stream_with_bytes(sse_body: &[u8]) -> Vec<ResponseEvent> {
4949
base_url: Some(format!("{}/v1", server.uri())),
5050
env_key: None,
5151
env_key_instructions: None,
52+
secret_key: None,
5253
wire_api: WireApi::Chat,
5354
query_params: None,
5455
http_headers: None,

codex-rs/core/tests/responses_headers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ async fn responses_stream_includes_task_type_header() {
3838
base_url: Some(format!("{}/v1", server.uri())),
3939
env_key: None,
4040
env_key_instructions: None,
41+
secret_key: None,
4142
wire_api: WireApi::Responses,
4243
query_params: None,
4344
http_headers: None,

codex-rs/core/tests/suite/client.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
632632
base_url: Some(format!("{}/openai", server.uri())),
633633
env_key: None,
634634
env_key_instructions: None,
635+
secret_key: None,
635636
wire_api: WireApi::Responses,
636637
query_params: None,
637638
http_headers: None,
@@ -1115,6 +1116,7 @@ async fn azure_overrides_assign_properties_used_for_responses_url() {
11151116
base_url: Some(format!("{}/openai", server.uri())),
11161117
// Reuse the existing environment variable to avoid using unsafe code
11171118
env_key: Some(existing_env_var_with_random_value.to_string()),
1119+
secret_key: None,
11181120
query_params: Some(std::collections::HashMap::from([(
11191121
"api-version".to_string(),
11201122
"2025-04-01-preview".to_string(),
@@ -1197,6 +1199,7 @@ async fn env_var_overrides_loaded_auth() {
11971199
"2025-04-01-preview".to_string(),
11981200
)])),
11991201
env_key_instructions: None,
1202+
secret_key: None,
12001203
wire_api: WireApi::Responses,
12011204
http_headers: Some(std::collections::HashMap::from([(
12021205
"Custom-Header".to_string(),

codex-rs/core/tests/suite/stream_error_allows_next_turn.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ async fn continue_after_stream_error() {
6666
base_url: Some(format!("{}/v1", server.uri())),
6767
env_key: Some("PATH".into()),
6868
env_key_instructions: None,
69+
secret_key: None,
6970
wire_api: WireApi::Responses,
7071
query_params: None,
7172
http_headers: None,

codex-rs/core/tests/suite/stream_no_completed.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ async fn retries_on_early_close() {
7373
// provider is not set.
7474
env_key: Some("PATH".into()),
7575
env_key_instructions: None,
76+
secret_key: None,
7677
wire_api: WireApi::Responses,
7778
query_params: None,
7879
http_headers: None,

0 commit comments

Comments
 (0)