fix: dont compact standalone websearch schema (#24660)

add new `parse_tool_input_schema_without_compaction` to bypass the
existing compaction/trimming of client-provided tool schemas that are
over 4k bytes.

we want this for standalone web search to keep field guidance/metadata
on certain fields; this keeps us closer to parity with existing hosted
tool schema (which didnt go through this 4k byte filter).
This commit is contained in:
sayan-oai
2026-05-26 18:05:19 -07:00
committed by GitHub
parent 0d37db4b2b
commit 9fe55d68e6
6 changed files with 53 additions and 10 deletions

View File

@@ -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),

View File

@@ -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;

View File

@@ -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<ToolCall> 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}"),
};

View File

@@ -157,10 +157,26 @@ impl From<JsonSchema> for AdditionalProperties {
/// Parse the tool `input_schema` or return an error for invalid schema.
pub fn parse_tool_input_schema(input_schema: &JsonValue) -> Result<JsonSchema, serde_json::Error> {
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<JsonSchema, serde_json::Error> {
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<JsonSchema, serde_json::Error> {
let schema: JsonSchema = serde_json::from_value(input_schema)?;
if matches!(
schema.schema_type,

View File

@@ -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<String, serde_json::V
}
#[test]
fn parse_large_tool_input_schema_stops_after_descriptions_when_under_budget() {
let schema = parse_tool_input_schema(&serde_json::json!({
fn parse_large_tool_input_schema_compacts_descriptions_only_on_default_path() {
let input_schema = serde_json::json!({
"type": "object",
"description": "x".repeat(4_500),
"properties": {
@@ -806,8 +807,8 @@ fn parse_large_tool_input_schema_stops_after_descriptions_when_under_budget() {
"description": "Metadata value"
}
}
}))
.expect("parse schema");
});
let schema = parse_tool_input_schema(&input_schema).expect("parse schema");
assert_eq!(
serde_json::to_value(schema).expect("serialize schema"),
@@ -825,6 +826,26 @@ fn parse_large_tool_input_schema_stops_after_descriptions_when_under_budget() {
}
})
);
let schema = parse_tool_input_schema_without_compaction(&input_schema).expect("parse schema");
assert_eq!(
serde_json::to_value(schema).expect("serialize schema"),
serde_json::json!({
"type": "object",
"description": "x".repeat(4_500),
"properties": {
"metadata": {
"$ref": "#/$defs/metadata"
}
},
"$defs": {
"metadata": {
"type": "string",
"description": "Metadata value"
}
}
})
);
}
#[test]

View File

@@ -35,6 +35,7 @@ pub use json_schema::JsonSchema;
pub use json_schema::JsonSchemaPrimitiveType;
pub use json_schema::JsonSchemaType;
pub use json_schema::parse_tool_input_schema;
pub use json_schema::parse_tool_input_schema_without_compaction;
pub use mcp_tool::mcp_call_tool_result_output_schema;
pub use mcp_tool::parse_mcp_tool;
pub use request_plugin_install::REQUEST_PLUGIN_INSTALL_APPROVAL_KIND_VALUE;