diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 3a2e2fcc3a..73fa23fc59 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -9743,6 +9743,17 @@ } ] }, + "client_search_provider": { + "anyOf": [ + { + "$ref": "#/definitions/v2/WebSearchProvider" + }, + { + "type": "null" + } + ], + "description": "Effective tools.client_search_provider hint. Model-selected providers take precedence." + }, "compact_prompt": { "type": [ "string", @@ -28047,6 +28058,14 @@ ], "type": "string" }, + "WebSearchProvider": { + "description": "Provider preference selected by the resolved model catalog entry.", + "enum": [ + "standalone", + "search_mcp" + ], + "type": "string" + }, "WebSearchToolConfig": { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 41d82db6f1..bc2a78adbc 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -5524,6 +5524,17 @@ } ] }, + "client_search_provider": { + "anyOf": [ + { + "$ref": "#/definitions/WebSearchProvider" + }, + { + "type": "null" + } + ], + "description": "Effective tools.client_search_provider hint. Model-selected providers take precedence." + }, "compact_prompt": { "type": [ "string", @@ -25750,6 +25761,14 @@ ], "type": "string" }, + "WebSearchProvider": { + "description": "Provider preference selected by the resolved model catalog entry.", + "enum": [ + "standalone", + "search_mcp" + ], + "type": "string" + }, "WebSearchToolConfig": { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json index 66a190dfe6..4fd6ad209c 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json @@ -511,6 +511,17 @@ } ] }, + "client_search_provider": { + "anyOf": [ + { + "$ref": "#/definitions/WebSearchProvider" + }, + { + "type": "null" + } + ], + "description": "Effective tools.client_search_provider hint. Model-selected providers take precedence." + }, "compact_prompt": { "type": [ "string", @@ -1116,6 +1127,14 @@ ], "type": "string" }, + "WebSearchProvider": { + "description": "Provider preference selected by the resolved model catalog entry.", + "enum": [ + "standalone", + "search_mcp" + ], + "type": "string" + }, "WebSearchToolConfig": { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst index 12ddd926f1..cd5e409139 100644 Binary files a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst and b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-experimental.json.zst differ diff --git a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst index d284219e4a..8607d80431 100644 Binary files a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst and b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst differ diff --git a/codex-rs/app-server-protocol/schema/typescript/WebSearchProvider.ts b/codex-rs/app-server-protocol/schema/typescript/WebSearchProvider.ts new file mode 100644 index 0000000000..4c3b377b71 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/WebSearchProvider.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Provider preference selected by the resolved model catalog entry. + */ +export type WebSearchProvider = "standalone" | "search_mcp"; diff --git a/codex-rs/app-server-protocol/schema/typescript/index.ts b/codex-rs/app-server-protocol/schema/typescript/index.ts index 3135f430e9..8eb856fa10 100644 --- a/codex-rs/app-server-protocol/schema/typescript/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/index.ts @@ -93,5 +93,6 @@ export type { WebSearchContextSize } from "./WebSearchContextSize"; export type { WebSearchItem } from "./WebSearchItem"; export type { WebSearchLocation } from "./WebSearchLocation"; export type { WebSearchMode } from "./WebSearchMode"; +export type { WebSearchProvider } from "./WebSearchProvider"; export type { WebSearchToolConfig } from "./WebSearchToolConfig"; export * as v2 from "./v2"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/Config.ts b/codex-rs/app-server-protocol/schema/typescript/v2/Config.ts index 4d0c409796..e80beb8e32 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/Config.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/Config.ts @@ -7,6 +7,7 @@ import type { ReasoningEffort } from "../ReasoningEffort"; import type { ReasoningSummary } from "../ReasoningSummary"; import type { Verbosity } from "../Verbosity"; import type { WebSearchMode } from "../WebSearchMode"; +import type { WebSearchProvider } from "../WebSearchProvider"; import type { JsonValue } from "../serde_json/JsonValue"; import type { AnalyticsConfig } from "./AnalyticsConfig"; import type { ApprovalsReviewer } from "./ApprovalsReviewer"; @@ -22,4 +23,7 @@ export type Config = {model: string | null, review_model: string | null, model_c * [UNSTABLE] Optional default for where approval requests are routed for * review. */ -approvals_reviewer: ApprovalsReviewer | null, sandbox_mode: SandboxMode | null, sandbox_workspace_write: SandboxWorkspaceWrite | null, forced_chatgpt_workspace_id: ForcedChatgptWorkspaceIds | null, forced_login_method: ForcedLoginMethod | null, web_search: WebSearchMode | null, tools: ToolsV2 | null, instructions: string | null, developer_instructions: string | null, compact_prompt: string | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, service_tier: string | null, analytics: AnalyticsConfig | null, browser_use: BrowserUseConfig | null, computer_use: ComputerUseConfig | null, desktop: { [key in string]?: JsonValue } | null} & ({ [key in string]?: number | string | boolean | Array | { [key in string]?: JsonValue } | null }); +approvals_reviewer: ApprovalsReviewer | null, sandbox_mode: SandboxMode | null, sandbox_workspace_write: SandboxWorkspaceWrite | null, forced_chatgpt_workspace_id: ForcedChatgptWorkspaceIds | null, forced_login_method: ForcedLoginMethod | null, web_search: WebSearchMode | null, /** + * Effective tools.client_search_provider hint. Model-selected providers take precedence. + */ +client_search_provider: WebSearchProvider | null, tools: ToolsV2 | null, instructions: string | null, developer_instructions: string | null, compact_prompt: string | null, model_reasoning_effort: ReasoningEffort | null, model_reasoning_summary: ReasoningSummary | null, model_verbosity: Verbosity | null, service_tier: string | null, analytics: AnalyticsConfig | null, browser_use: BrowserUseConfig | null, computer_use: ComputerUseConfig | null, desktop: { [key in string]?: JsonValue } | null} & ({ [key in string]?: number | string | boolean | Array | { [key in string]?: JsonValue } | null }); diff --git a/codex-rs/app-server-protocol/src/protocol/v2/config.rs b/codex-rs/app-server-protocol/src/protocol/v2/config.rs index 09006baf7e..2158fa23aa 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/config.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/config.rs @@ -297,6 +297,8 @@ pub struct Config { pub forced_chatgpt_workspace_id: Option, pub forced_login_method: Option, pub web_search: Option, + /// Effective tools.client_search_provider hint. Model-selected providers take precedence. + pub client_search_provider: Option, pub tools: Option, pub instructions: Option, pub developer_instructions: Option, diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs index 049cef5ed6..6990a4cf07 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs @@ -2130,6 +2130,7 @@ fn config_granular_approval_policy_is_marked_experimental() { forced_chatgpt_workspace_id: None, forced_login_method: None, web_search: None, + client_search_provider: None, tools: None, instructions: None, developer_instructions: None, @@ -2165,6 +2166,7 @@ fn config_approvals_reviewer_is_marked_experimental() { forced_chatgpt_workspace_id: None, forced_login_method: None, web_search: None, + client_search_provider: None, tools: None, instructions: None, developer_instructions: None, diff --git a/codex-rs/app-server/src/config_manager_service.rs b/codex-rs/app-server/src/config_manager_service.rs index 7b8414f015..25d51ed2e0 100644 --- a/codex-rs/app-server/src/config_manager_service.rs +++ b/codex-rs/app-server/src/config_manager_service.rs @@ -161,8 +161,12 @@ impl ConfigManager { let json_value = serde_json::to_value(&effective_config_toml) .map_err(|err| ConfigManagerError::json("failed to serialize configuration", err))?; - let config: ApiConfig = serde_json::from_value(json_value) + let mut config: ApiConfig = serde_json::from_value(json_value) .map_err(|err| ConfigManagerError::json("failed to deserialize configuration", err))?; + config.client_search_provider = effective_config_toml + .tools + .as_ref() + .and_then(|tools| tools.client_search_provider); let mut origins = layers.origins_with_path_filter(|segments| { layers diff --git a/codex-rs/app-server/tests/common/models_cache.rs b/codex-rs/app-server/tests/common/models_cache.rs index 411ebabc4b..0fc60d317c 100644 --- a/codex-rs/app-server/tests/common/models_cache.rs +++ b/codex-rs/app-server/tests/common/models_cache.rs @@ -56,6 +56,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo { availability_nux: preset.availability_nux.clone(), apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/codex-api/tests/models_integration.rs b/codex-rs/codex-api/tests/models_integration.rs index 05d1806c1f..49443c6ab6 100644 --- a/codex-rs/codex-api/tests/models_integration.rs +++ b/codex-rs/codex-api/tests/models_integration.rs @@ -148,6 +148,7 @@ async fn models_client_hits_models_endpoint() { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/config/src/config_toml.rs b/codex-rs/config/src/config_toml.rs index cd1c40056e..ed06a95fd7 100644 --- a/codex-rs/config/src/config_toml.rs +++ b/codex-rs/config/src/config_toml.rs @@ -706,6 +706,8 @@ pub struct RealtimeAudioToml { #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)] #[schemars(deny_unknown_fields)] pub struct ToolsToml { + /// Client provider preference when the model does not select a provider. + pub client_search_provider: Option, #[serde( default, deserialize_with = "deserialize_optional_web_search_tool_config" diff --git a/codex-rs/core/config.schema.json b/codex-rs/core/config.schema.json index 8a2b679775..cd565c72ef 100644 --- a/codex-rs/core/config.schema.json +++ b/codex-rs/core/config.schema.json @@ -1104,6 +1104,9 @@ "hooks": { "type": "boolean" }, + "hosted_search_policy": { + "type": "boolean" + }, "image_detail_original": { "type": "boolean" }, @@ -5056,6 +5059,14 @@ "ToolsToml": { "additionalProperties": false, "properties": { + "client_search_provider": { + "allOf": [ + { + "$ref": "#/definitions/WebSearchProvider" + } + ], + "description": "Client provider preference when the model does not select a provider." + }, "experimental_request_user_input": { "$ref": "#/definitions/ExperimentalRequestUserInput" }, @@ -7342,6 +7353,14 @@ ], "type": "string" }, + "WebSearchProvider": { + "description": "Provider preference selected by the resolved model catalog entry.", + "enum": [ + "standalone", + "search_mcp" + ], + "type": "string" + }, "WebSearchToolConfig": { "additionalProperties": false, "properties": { @@ -7845,6 +7864,9 @@ "hooks": { "type": "boolean" }, + "hosted_search_policy": { + "type": "boolean" + }, "image_detail_original": { "type": "boolean" }, diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 95de21d773..9c52a7394c 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -493,8 +493,7 @@ web_search = true cfg.tools, Some(ToolsToml { web_search: None, - experimental_request_user_input: None, - update_plan: None, + ..Default::default() }) ); } @@ -513,8 +512,7 @@ web_search = false cfg.tools, Some(ToolsToml { web_search: None, - experimental_request_user_input: None, - update_plan: None, + ..Default::default() }) ); } @@ -531,9 +529,8 @@ fn tools_experimental_request_user_input_defaults_to_enabled() { assert_eq!( cfg.tools, Some(ToolsToml { - web_search: None, experimental_request_user_input: Some(ExperimentalRequestUserInput { enabled: true }), - update_plan: None, + ..Default::default() }) ); } @@ -551,9 +548,8 @@ enabled = false assert_eq!( cfg.tools, Some(ToolsToml { - web_search: None, experimental_request_user_input: Some(ExperimentalRequestUserInput { enabled: false }), - update_plan: None, + ..Default::default() }) ); } @@ -569,6 +565,7 @@ async fn load_config_resolves_experimental_request_user_input_enabled() -> std:: enabled: false, }), update_plan: None, + ..Default::default() }), ..ConfigToml::default() }, diff --git a/codex-rs/core/tests/suite/auto_review.rs b/codex-rs/core/tests/suite/auto_review.rs index 2eae76fcc9..470a81579b 100644 --- a/codex-rs/core/tests/suite/auto_review.rs +++ b/codex-rs/core/tests/suite/auto_review.rs @@ -673,6 +673,7 @@ fn remote_model_with_auto_review_override(slug: &str, review_model: &str) -> Mod availability_nux: None, apply_patch_tool_type: Some(ApplyPatchToolType::Freeform), web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/model_switching.rs b/codex-rs/core/tests/suite/model_switching.rs index 7f580eedaa..3e33e14d2c 100644 --- a/codex-rs/core/tests/suite/model_switching.rs +++ b/codex-rs/core/tests/suite/model_switching.rs @@ -152,6 +152,7 @@ fn test_model_info( availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), @@ -1286,6 +1287,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result< availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(large_context_window), diff --git a/codex-rs/core/tests/suite/models_cache_ttl.rs b/codex-rs/core/tests/suite/models_cache_ttl.rs index fd8c8560b2..d37d67b115 100644 --- a/codex-rs/core/tests/suite/models_cache_ttl.rs +++ b/codex-rs/core/tests/suite/models_cache_ttl.rs @@ -668,6 +668,7 @@ fn test_remote_model(slug: &str, priority: i32) -> ModelInfo { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 6edb1cb3ad..46a523f0ae 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -608,6 +608,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), @@ -885,6 +886,7 @@ async fn remote_models_apply_legacy_instructions(auth: CodexAuth) -> Result<()> availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), @@ -1470,6 +1472,7 @@ fn test_remote_model_with_policy( availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy, supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 64900ec022..fa2cf80c94 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -3662,6 +3662,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/spawn_agent_description.rs b/codex-rs/core/tests/suite/spawn_agent_description.rs index e4f3a20703..3a2dfb41c7 100644 --- a/codex-rs/core/tests/suite/spawn_agent_description.rs +++ b/codex-rs/core/tests/suite/spawn_agent_description.rs @@ -119,6 +119,7 @@ fn test_model_info( availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 1b0eeb2fdc..8f0c405a7a 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -1650,6 +1650,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an availability_nux: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index 8d2bab4c76..f92ba78a00 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -195,6 +195,8 @@ pub enum Feature { WebSearchCached, /// Expose the extension-backed standalone web search tool. StandaloneWebSearch, + /// Let the host authorize MCP search independently of native search through per-turn policy. + HostedSearchPolicy, /// Use the legacy Landlock Linux sandbox fallback instead of the default /// bubblewrap pipeline. UseLegacyLandlock, @@ -1393,6 +1395,12 @@ pub const FEATURES: &[FeatureSpec] = &[ stage: Stage::UnderDevelopment, default_enabled: false, }, + FeatureSpec { + id: Feature::HostedSearchPolicy, + key: "hosted_search_policy", + stage: Stage::UnderDevelopment, + default_enabled: false, + }, FeatureSpec { id: Feature::SearchTool, key: "search_tool", diff --git a/codex-rs/models-manager/src/model_info.rs b/codex-rs/models-manager/src/model_info.rs index f7e6f5b943..ca242dac85 100644 --- a/codex-rs/models-manager/src/model_info.rs +++ b/codex-rs/models-manager/src/model_info.rs @@ -123,6 +123,7 @@ pub fn model_info_from_slug(slug: &str) -> ModelInfo { default_verbosity: None, apply_patch_tool_type: None, web_search_tool_type: WebSearchToolType::Text, + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: Some(272_000), diff --git a/codex-rs/prompts/src/model_instructions_tests.rs b/codex-rs/prompts/src/model_instructions_tests.rs index 2360c5516b..200afcdf91 100644 --- a/codex-rs/prompts/src/model_instructions_tests.rs +++ b/codex-rs/prompts/src/model_instructions_tests.rs @@ -34,6 +34,7 @@ fn test_model(model_messages: Option) -> ModelInfo { default_verbosity: None, apply_patch_tool_type: None, web_search_tool_type: Default::default(), + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: None, diff --git a/codex-rs/protocol/src/openai_models.rs b/codex-rs/protocol/src/openai_models.rs index 1f0275ea7b..180a01f8b3 100644 --- a/codex-rs/protocol/src/openai_models.rs +++ b/codex-rs/protocol/src/openai_models.rs @@ -348,6 +348,14 @@ pub enum WebSearchToolType { TextAndImage, } +/// Provider preference selected by the resolved model catalog entry. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, TS, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum WebSearchProvider { + Standalone, + SearchMcp, +} + /// Server-provided truncation policy metadata for a model. #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, TS, JsonSchema)] #[serde(rename_all = "snake_case")] @@ -460,6 +468,8 @@ pub struct ModelInfo { pub apply_patch_tool_type: Option, #[serde(default)] pub web_search_tool_type: WebSearchToolType, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub web_search_provider: Option, pub truncation_policy: TruncationPolicyConfig, #[serde(default)] pub supports_image_detail_original: bool, @@ -1213,6 +1223,7 @@ mod tests { default_verbosity: None, apply_patch_tool_type: None, web_search_tool_type: WebSearchToolType::Text, + web_search_provider: None, truncation_policy: TruncationPolicyConfig::bytes(/*limit*/ 10_000), supports_image_detail_original: false, context_window: None, diff --git a/sdk/python/src/openai_codex/generated/v2_all.py b/sdk/python/src/openai_codex/generated/v2_all.py index 35688bfb6f..f56db399fd 100644 --- a/sdk/python/src/openai_codex/generated/v2_all.py +++ b/sdk/python/src/openai_codex/generated/v2_all.py @@ -7081,6 +7081,11 @@ class WebSearchMode(Enum): live = "live" +class WebSearchProvider(Enum): + standalone = "standalone" + search_mcp = "search_mcp" + + class WebSearchToolConfig(BaseModel): model_config = ConfigDict( extra="forbid", @@ -11595,6 +11600,12 @@ class Config(BaseModel): ), ] = None browser_use: BrowserUseConfig | None = None + client_search_provider: Annotated[ + WebSearchProvider | None, + Field( + description="Effective tools.client_search_provider hint. Model-selected providers take precedence." + ), + ] = None compact_prompt: str | None = None computer_use: ComputerUseConfig | None = None desktop: dict[str, Any] | None = None