diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index f415c3604a8..6392b3e70ca 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -655,13 +655,11 @@ fn build_responses_headers( let mut headers = experimental_feature_headers(config); headers.insert( WEB_SEARCH_ELIGIBLE_HEADER, - HeaderValue::from_static( - if matches!(config.web_search_mode, Some(WebSearchMode::Disabled)) { - "false" - } else { - "true" - }, - ), + HeaderValue::from_static(if config.web_search_mode == WebSearchMode::Disabled { + "false" + } else { + "true" + }), ); if let Some(turn_state) = turn_state && let Some(state) = turn_state.get() diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 5e535f51307..41e148e113a 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -2824,7 +2824,7 @@ async fn spawn_review_thread( let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &review_model_info, features: &review_features, - web_search_mode: Some(review_web_search_mode), + web_search_mode: review_web_search_mode, }); let review_prompt = resolved.prompt.clone(); @@ -2836,7 +2836,7 @@ async fn spawn_review_thread( let mut per_turn_config = (*config).clone(); per_turn_config.model = Some(model.clone()); per_turn_config.features = review_features.clone(); - per_turn_config.web_search_mode = Some(review_web_search_mode); + per_turn_config.web_search_mode = review_web_search_mode; let otel_manager = parent_turn_context .client diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index dbccb2bef1c..8744b756bfe 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -304,8 +304,8 @@ pub struct Config { /// model info's default preference. pub include_apply_patch_tool: bool, - /// Explicit or feature-derived web search mode. - pub web_search_mode: Option, + /// Explicit or feature-derived web search mode. Defaults to cached. + pub web_search_mode: WebSearchMode, /// If set to `true`, used only the experimental unified exec tool. pub use_experimental_unified_exec_tool: bool, @@ -1205,17 +1205,17 @@ fn resolve_web_search_mode( config_toml: &ConfigToml, config_profile: &ConfigProfile, features: &Features, -) -> Option { +) -> WebSearchMode { if let Some(mode) = config_profile.web_search.or(config_toml.web_search) { - return Some(mode); + return mode; } if features.enabled(Feature::WebSearchCached) { - return Some(WebSearchMode::Cached); + return WebSearchMode::Cached; } if features.enabled(Feature::WebSearchRequest) { - return Some(WebSearchMode::Live); + return WebSearchMode::Live; } - None + WebSearchMode::Cached } impl Config { @@ -2264,12 +2264,15 @@ trust_level = "trusted" } #[test] - fn web_search_mode_uses_none_if_unset() { + fn web_search_mode_defaults_to_cached_if_unset() { let cfg = ConfigToml::default(); let profile = ConfigProfile::default(); let features = Features::with_defaults(); - assert_eq!(resolve_web_search_mode(&cfg, &profile, &features), None); + assert_eq!( + resolve_web_search_mode(&cfg, &profile, &features), + WebSearchMode::Cached + ); } #[test] @@ -2284,7 +2287,7 @@ trust_level = "trusted" assert_eq!( resolve_web_search_mode(&cfg, &profile, &features), - Some(WebSearchMode::Live) + WebSearchMode::Live ); } @@ -2300,7 +2303,7 @@ trust_level = "trusted" assert_eq!( resolve_web_search_mode(&cfg, &profile, &features), - Some(WebSearchMode::Disabled) + WebSearchMode::Disabled ); } @@ -3737,7 +3740,7 @@ model_verbosity = "high" forced_chatgpt_workspace_id: None, forced_login_method: None, include_apply_patch_tool: false, - web_search_mode: None, + web_search_mode: WebSearchMode::Cached, use_experimental_unified_exec_tool: false, ghost_snapshot: GhostSnapshotConfig::default(), features: Features::with_defaults(), @@ -3820,7 +3823,7 @@ model_verbosity = "high" forced_chatgpt_workspace_id: None, forced_login_method: None, include_apply_patch_tool: false, - web_search_mode: None, + web_search_mode: WebSearchMode::Cached, use_experimental_unified_exec_tool: false, ghost_snapshot: GhostSnapshotConfig::default(), features: Features::with_defaults(), @@ -3918,7 +3921,7 @@ model_verbosity = "high" forced_chatgpt_workspace_id: None, forced_login_method: None, include_apply_patch_tool: false, - web_search_mode: None, + web_search_mode: WebSearchMode::Cached, use_experimental_unified_exec_tool: false, ghost_snapshot: GhostSnapshotConfig::default(), features: Features::with_defaults(), @@ -4002,7 +4005,7 @@ model_verbosity = "high" forced_chatgpt_workspace_id: None, forced_login_method: None, include_apply_patch_tool: false, - web_search_mode: None, + web_search_mode: WebSearchMode::Cached, use_experimental_unified_exec_tool: false, ghost_snapshot: GhostSnapshotConfig::default(), features: Features::with_defaults(), diff --git a/codex-rs/core/src/tasks/review.rs b/codex-rs/core/src/tasks/review.rs index d156d3e0d5d..89dbaf90feb 100644 --- a/codex-rs/core/src/tasks/review.rs +++ b/codex-rs/core/src/tasks/review.rs @@ -86,7 +86,7 @@ async fn start_review_conversation( let mut sub_agent_config = config.as_ref().clone(); // Carry over review-only feature restrictions so the delegate cannot // re-enable blocked tools (web search, view image). - sub_agent_config.web_search_mode = Some(WebSearchMode::Disabled); + sub_agent_config.web_search_mode = WebSearchMode::Disabled; // Set explicit review rubric for the sub-agent sub_agent_config.base_instructions = Some(crate::REVIEW_PROMPT.to_string()); diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index 33010e58e17..64f4053bb59 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -27,7 +27,7 @@ use std::collections::HashMap; pub(crate) struct ToolsConfig { pub shell_type: ConfigShellToolType, pub apply_patch_tool_type: Option, - pub web_search_mode: Option, + pub web_search_mode: WebSearchMode, pub collab_tools: bool, pub collaboration_modes_tools: bool, pub experimental_supported_tools: Vec, @@ -36,7 +36,7 @@ pub(crate) struct ToolsConfig { pub(crate) struct ToolsConfigParams<'a> { pub(crate) model_info: &'a ModelInfo, pub(crate) features: &'a Features, - pub(crate) web_search_mode: Option, + pub(crate) web_search_mode: WebSearchMode, } impl ToolsConfig { @@ -1374,17 +1374,17 @@ pub(crate) fn build_specs( } match config.web_search_mode { - Some(WebSearchMode::Cached) => { + WebSearchMode::Cached => { builder.push_spec(ToolSpec::WebSearch { external_web_access: Some(false), }); } - Some(WebSearchMode::Live) => { + WebSearchMode::Live => { builder.push_spec(ToolSpec::WebSearch { external_web_access: Some(true), }); } - Some(WebSearchMode::Disabled) | None => {} + WebSearchMode::Disabled => {} } builder.push_spec_with_parallel_support(create_view_image_tool(), true); @@ -1546,7 +1546,7 @@ mod tests { let config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Live), + web_search_mode: WebSearchMode::Live, }); let (tools, _) = build_specs(&config, None, &[]).build(); @@ -1610,7 +1610,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); assert_contains_tool_names( @@ -1628,7 +1628,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); assert!( @@ -1640,7 +1640,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); assert_contains_tool_names(&tools, &["request_user_input"]); @@ -1649,7 +1649,7 @@ mod tests { fn assert_model_tools( model_slug: &str, features: &Features, - web_search_mode: Option, + web_search_mode: WebSearchMode, expected_tools: &[&str], ) { let config = test_config(); @@ -1673,7 +1673,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); @@ -1695,7 +1695,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Live), + web_search_mode: WebSearchMode::Live, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); @@ -1715,7 +1715,7 @@ mod tests { assert_model_tools( "gpt-5-codex", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "shell_command", "list_mcp_resources", @@ -1737,7 +1737,7 @@ mod tests { assert_model_tools( "gpt-5.1-codex", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "shell_command", "list_mcp_resources", @@ -1760,7 +1760,7 @@ mod tests { assert_model_tools( "gpt-5-codex", &features, - Some(WebSearchMode::Live), + WebSearchMode::Live, &[ "exec_command", "write_stdin", @@ -1784,7 +1784,7 @@ mod tests { assert_model_tools( "gpt-5.1-codex", &features, - Some(WebSearchMode::Live), + WebSearchMode::Live, &[ "exec_command", "write_stdin", @@ -1807,7 +1807,7 @@ mod tests { assert_model_tools( "codex-mini-latest", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "local_shell", "list_mcp_resources", @@ -1828,7 +1828,7 @@ mod tests { assert_model_tools( "gpt-5.1-codex-mini", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "shell_command", "list_mcp_resources", @@ -1850,7 +1850,7 @@ mod tests { assert_model_tools( "gpt-5", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "shell", "list_mcp_resources", @@ -1871,7 +1871,7 @@ mod tests { assert_model_tools( "gpt-5.1", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "shell_command", "list_mcp_resources", @@ -1893,7 +1893,7 @@ mod tests { assert_model_tools( "exp-5.1", &features, - Some(WebSearchMode::Cached), + WebSearchMode::Cached, &[ "exec_command", "write_stdin", @@ -1917,7 +1917,7 @@ mod tests { assert_model_tools( "codex-mini-latest", &features, - Some(WebSearchMode::Live), + WebSearchMode::Live, &[ "exec_command", "write_stdin", @@ -1941,7 +1941,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Live), + web_search_mode: WebSearchMode::Live, }); let (tools, _) = build_specs(&tools_config, Some(HashMap::new()), &[]).build(); @@ -1963,7 +1963,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); @@ -1982,7 +1982,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs(&tools_config, None, &[]).build(); @@ -2013,7 +2013,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Live), + web_search_mode: WebSearchMode::Live, }); let (tools, _) = build_specs( &tools_config, @@ -2109,7 +2109,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); // Intentionally construct a map with keys that would sort alphabetically. @@ -2186,7 +2186,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs( @@ -2244,7 +2244,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs( @@ -2299,7 +2299,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs( @@ -2356,7 +2356,7 @@ mod tests { let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs( @@ -2469,7 +2469,7 @@ Examples of valid command strings: let tools_config = ToolsConfig::new(&ToolsConfigParams { model_info: &model_info, features: &features, - web_search_mode: Some(WebSearchMode::Cached), + web_search_mode: WebSearchMode::Cached, }); let (tools, _) = build_specs( &tools_config, diff --git a/codex-rs/core/tests/responses_headers.rs b/codex-rs/core/tests/responses_headers.rs index 22d9fa8b796..9e268a2c50c 100644 --- a/codex-rs/core/tests/responses_headers.rs +++ b/codex-rs/core/tests/responses_headers.rs @@ -264,7 +264,7 @@ async fn responses_stream_includes_web_search_eligible_header_false_when_disable let test = test_codex() .with_config(|config| { - config.web_search_mode = Some(WebSearchMode::Disabled); + config.web_search_mode = WebSearchMode::Disabled; }) .build(&server) .await diff --git a/codex-rs/core/tests/suite/model_tools.rs b/codex-rs/core/tests/suite/model_tools.rs index b08b5281c8f..0c8277e9155 100644 --- a/codex-rs/core/tests/suite/model_tools.rs +++ b/codex-rs/core/tests/suite/model_tools.rs @@ -38,7 +38,7 @@ async fn collect_tool_identifiers_for_model(model: &str) -> Vec { .with_model(model) // Keep tool expectations stable when the default web_search mode changes. .with_config(|config| { - config.web_search_mode = Some(WebSearchMode::Cached); + config.web_search_mode = WebSearchMode::Cached; config.features.enable(Feature::CollaborationModes); }); let test = builder diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index 686428b21a4..32969bcf5a2 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -92,7 +92,7 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> { config.user_instructions = Some("be consistent and helpful".to_string()); config.model = Some("gpt-5.1-codex-max".to_string()); // Keep tool expectations stable when the default web_search mode changes. - config.web_search_mode = Some(WebSearchMode::Cached); + config.web_search_mode = WebSearchMode::Cached; config.features.enable(Feature::CollaborationModes); }) .build(&server) diff --git a/codex-rs/core/tests/suite/web_search_cached.rs b/codex-rs/core/tests/suite/web_search_cached.rs index 1a69d8b7370..261efaf942b 100644 --- a/codex-rs/core/tests/suite/web_search_cached.rs +++ b/codex-rs/core/tests/suite/web_search_cached.rs @@ -35,7 +35,7 @@ async fn web_search_mode_cached_sets_external_web_access_false_in_request_body() let mut builder = test_codex() .with_model("gpt-5-codex") .with_config(|config| { - config.web_search_mode = Some(WebSearchMode::Cached); + config.web_search_mode = WebSearchMode::Cached; }); let test = builder .build(&server) @@ -67,7 +67,7 @@ async fn web_search_mode_takes_precedence_over_legacy_flags_in_request_body() { .with_model("gpt-5-codex") .with_config(|config| { config.features.enable(Feature::WebSearchRequest); - config.web_search_mode = Some(WebSearchMode::Cached); + config.web_search_mode = WebSearchMode::Cached; }); let test = builder .build(&server) diff --git a/codex-rs/protocol/src/config_types.rs b/codex-rs/protocol/src/config_types.rs index ba6b12aadf2..00b9bc0e800 100644 --- a/codex-rs/protocol/src/config_types.rs +++ b/codex-rs/protocol/src/config_types.rs @@ -94,8 +94,8 @@ pub enum Personality { #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] pub enum WebSearchMode { - #[default] Disabled, + #[default] Cached, Live, }