diff --git a/codex-rs/app-server/tests/suite/v2/web_search.rs b/codex-rs/app-server/tests/suite/v2/web_search.rs index 58b2ff91a8..927f14ca9d 100644 --- a/codex-rs/app-server/tests/suite/v2/web_search.rs +++ b/codex-rs/app-server/tests/suite/v2/web_search.rs @@ -112,9 +112,12 @@ async fn standalone_web_search_round_trips_encrypted_output() -> Result<()> { assert_eq!(requests.len(), 2); let first_response = requests[0].body_json(); - assert!( - requests[0].tool_by_name("web", "run").is_some(), - "web.run should be sent to the model" + let web_run = requests[0] + .tool_by_name("web", "run") + .context("web.run should be sent to the model")?; + assert_eq!( + web_run.pointer("/parameters/properties/time/description"), + Some(&json!("Get time for the given UTC offsets.")) ); assert!( !has_hosted_web_search(&first_response), diff --git a/codex-rs/ext/extension-api/src/lib.rs b/codex-rs/ext/extension-api/src/lib.rs index a7c5c87e52..f3c3dc526e 100644 --- a/codex-rs/ext/extension-api/src/lib.rs +++ b/codex-rs/ext/extension-api/src/lib.rs @@ -21,6 +21,7 @@ pub use codex_tools::ToolOutput; pub use codex_tools::ToolPayload; pub use codex_tools::ToolSpec; pub use codex_tools::parse_tool_input_schema; +pub use codex_tools::parse_tool_input_schema_without_compaction; pub use contributors::ApprovalReviewContributor; pub use contributors::ConfigContributor; pub use contributors::ContextContributor; diff --git a/codex-rs/ext/web-search/src/tool.rs b/codex-rs/ext/web-search/src/tool.rs index 1e1db2deca..875476db9a 100644 --- a/codex-rs/ext/web-search/src/tool.rs +++ b/codex-rs/ext/web-search/src/tool.rs @@ -10,7 +10,7 @@ use codex_extension_api::ToolExecutor; use codex_extension_api::ToolName; use codex_extension_api::ToolOutput; use codex_extension_api::ToolSpec; -use codex_extension_api::parse_tool_input_schema; +use codex_extension_api::parse_tool_input_schema_without_compaction; use codex_login::default_client::build_reqwest_client; use codex_model_provider::SharedModelProvider; use codex_tools::ResponsesApiNamespace; @@ -40,7 +40,8 @@ impl ToolExecutor for WebSearchTool { } fn spec(&self) -> ToolSpec { - let parameters = match parse_tool_input_schema(&commands_schema()) { + // parse schema without compaction that removes field metadata/descriptions to match hosted tool definition + let parameters = match parse_tool_input_schema_without_compaction(&commands_schema()) { Ok(parameters) => parameters, Err(err) => panic!("search command schema should parse: {err}"), }; diff --git a/codex-rs/tools/src/json_schema.rs b/codex-rs/tools/src/json_schema.rs index 02936d52d1..1b53ad9803 100644 --- a/codex-rs/tools/src/json_schema.rs +++ b/codex-rs/tools/src/json_schema.rs @@ -157,10 +157,26 @@ impl From for AdditionalProperties { /// Parse the tool `input_schema` or return an error for invalid schema. pub fn parse_tool_input_schema(input_schema: &JsonValue) -> Result { + let mut input_schema = prepare_tool_input_schema(input_schema); + compact_large_tool_schema(&mut input_schema); + deserialize_tool_input_schema(input_schema) +} + +/// Parse a trusted tool `input_schema` without running large-schema compaction. +pub fn parse_tool_input_schema_without_compaction( + input_schema: &JsonValue, +) -> Result { + deserialize_tool_input_schema(prepare_tool_input_schema(input_schema)) +} + +fn prepare_tool_input_schema(input_schema: &JsonValue) -> JsonValue { let mut input_schema = input_schema.clone(); sanitize_json_schema(&mut input_schema); prune_unreachable_definitions(&mut input_schema); - compact_large_tool_schema(&mut input_schema); + input_schema +} + +fn deserialize_tool_input_schema(input_schema: JsonValue) -> Result { let schema: JsonSchema = serde_json::from_value(input_schema)?; if matches!( schema.schema_type, diff --git a/codex-rs/tools/src/json_schema_tests.rs b/codex-rs/tools/src/json_schema_tests.rs index 52b30138c1..9315d43c00 100644 --- a/codex-rs/tools/src/json_schema_tests.rs +++ b/codex-rs/tools/src/json_schema_tests.rs @@ -3,6 +3,7 @@ use super::JsonSchema; use super::JsonSchemaPrimitiveType; use super::JsonSchemaType; use super::parse_tool_input_schema; +use super::parse_tool_input_schema_without_compaction; use pretty_assertions::assert_eq; use std::collections::BTreeMap; @@ -791,8 +792,8 @@ fn many_string_properties(count: usize) -> serde_json::Map