diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index e22cfe65a1..13e2c79c08 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -3767,6 +3767,7 @@ model_verbosity = "high" stream_idle_timeout_ms: Some(300_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let model_provider_map = { let mut model_provider_map = built_in_model_providers(); diff --git a/codex-rs/core/src/model_provider_info.rs b/codex-rs/core/src/model_provider_info.rs index 211822f48f..08c0134c60 100644 --- a/codex-rs/core/src/model_provider_info.rs +++ b/codex-rs/core/src/model_provider_info.rs @@ -113,6 +113,10 @@ pub struct ModelProviderInfo { /// Whether this provider supports the Responses API WebSocket transport. #[serde(default)] pub supports_websockets: bool, + + /// When true, skip reading `models_cache.json` and always fetch model metadata online. + #[serde(default)] + pub skip_models_cache: bool, } impl ModelProviderInfo { @@ -262,6 +266,7 @@ impl ModelProviderInfo { stream_idle_timeout_ms: None, requires_openai_auth: true, supports_websockets: true, + skip_models_cache: false, } } @@ -336,6 +341,7 @@ pub fn create_oss_provider_with_base_url(base_url: &str, wire_api: WireApi) -> M stream_idle_timeout_ms: None, requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, } } @@ -365,6 +371,7 @@ base_url = "http://localhost:11434/v1" stream_idle_timeout_ms: None, requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let provider: ModelProviderInfo = toml::from_str(azure_provider_toml).unwrap(); @@ -396,6 +403,7 @@ query_params = { api-version = "2025-04-01-preview" } stream_idle_timeout_ms: None, requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let provider: ModelProviderInfo = toml::from_str(azure_provider_toml).unwrap(); @@ -430,6 +438,7 @@ env_http_headers = { "X-Example-Env-Header" = "EXAMPLE_ENV_VAR" } stream_idle_timeout_ms: None, requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let provider: ModelProviderInfo = toml::from_str(azure_provider_toml).unwrap(); diff --git a/codex-rs/core/src/models_manager/manager.rs b/codex-rs/core/src/models_manager/manager.rs index fffc280736..0818697e83 100644 --- a/codex-rs/core/src/models_manager/manager.rs +++ b/codex-rs/core/src/models_manager/manager.rs @@ -255,6 +255,9 @@ impl ModelsManager { /// Attempt to satisfy the refresh from the cache when it matches the provider and TTL. async fn try_load_cache(&self) -> bool { + if self.provider.skip_models_cache { + return false; + } let _timer = codex_otel::start_global_timer("codex.remote_models.load_cache.duration_ms", &[]); let client_version = crate::models_manager::client_version_to_whole(); @@ -430,6 +433,7 @@ mod tests { stream_idle_timeout_ms: Some(5_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, } } diff --git a/codex-rs/core/tests/responses_headers.rs b/codex-rs/core/tests/responses_headers.rs index fd65bcf32a..44118e9099 100644 --- a/codex-rs/core/tests/responses_headers.rs +++ b/codex-rs/core/tests/responses_headers.rs @@ -60,6 +60,7 @@ async fn responses_stream_includes_subagent_header_on_review() { stream_idle_timeout_ms: Some(5_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let codex_home = TempDir::new().expect("failed to create TempDir"); @@ -159,6 +160,7 @@ async fn responses_stream_includes_subagent_header_on_other() { stream_idle_timeout_ms: Some(5_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let codex_home = TempDir::new().expect("failed to create TempDir"); @@ -314,6 +316,7 @@ async fn responses_respects_model_info_overrides_from_config() { stream_idle_timeout_ms: Some(5_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let codex_home = TempDir::new().expect("failed to create TempDir"); diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 62135127f2..2751590d6c 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -1238,6 +1238,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() { stream_idle_timeout_ms: Some(5_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let codex_home = TempDir::new().unwrap(); @@ -1767,6 +1768,7 @@ async fn azure_overrides_assign_properties_used_for_responses_url() { stream_idle_timeout_ms: None, requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; // Init session @@ -1851,6 +1853,7 @@ async fn env_var_overrides_loaded_auth() { stream_idle_timeout_ms: None, requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; // Init session diff --git a/codex-rs/core/tests/suite/client_websockets.rs b/codex-rs/core/tests/suite/client_websockets.rs index 15005caa48..eb2f96f708 100644 --- a/codex-rs/core/tests/suite/client_websockets.rs +++ b/codex-rs/core/tests/suite/client_websockets.rs @@ -390,6 +390,7 @@ fn websocket_provider(server: &WebSocketTestServer) -> ModelProviderInfo { stream_idle_timeout_ms: Some(5_000), requires_openai_auth: false, supports_websockets: true, + skip_models_cache: false, } } diff --git a/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs b/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs index 3562ec2500..c47ee7e632 100644 --- a/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs +++ b/codex-rs/core/tests/suite/stream_error_allows_next_turn.rs @@ -78,6 +78,7 @@ async fn continue_after_stream_error() { stream_idle_timeout_ms: Some(2_000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let TestCodex { codex, .. } = test_codex() diff --git a/codex-rs/core/tests/suite/stream_no_completed.rs b/codex-rs/core/tests/suite/stream_no_completed.rs index e8b130970e..83d9f1d5d5 100644 --- a/codex-rs/core/tests/suite/stream_no_completed.rs +++ b/codex-rs/core/tests/suite/stream_no_completed.rs @@ -86,6 +86,7 @@ async fn retries_on_early_close() { stream_idle_timeout_ms: Some(2000), requires_openai_auth: false, supports_websockets: false, + skip_models_cache: false, }; let TestCodex { codex, .. } = test_codex()