@@ -63,50 +63,54 @@ def validate_tool_use_name(tool: ToolUse) -> None:
6363 raise InvalidToolUseNameException (message )
6464
6565
66+ def _normalize_property (prop_name : str , prop_def : Any ) -> Dict [str , Any ]:
67+ """Normalize a single property definition.
68+
69+ Args:
70+ prop_name: The name of the property.
71+ prop_def: The property definition to normalize.
72+
73+ Returns:
74+ The normalized property definition.
75+ """
76+ if not isinstance (prop_def , dict ):
77+ return {"type" : "string" , "description" : f"Property { prop_name } " }
78+
79+ if prop_def .get ("type" ) == "object" and "properties" in prop_def :
80+ return normalize_schema (prop_def ) # Recursive call
81+
82+ # Copy existing property, ensuring defaults
83+ normalized_prop = prop_def .copy ()
84+ normalized_prop .setdefault ("type" , "string" )
85+ normalized_prop .setdefault ("description" , f"Property { prop_name } " )
86+ return normalized_prop
87+
88+
6689def normalize_schema (schema : Dict [str , Any ]) -> Dict [str , Any ]:
6790 """Normalize a JSON schema to match expectations.
6891
92+ This function recursively processes nested objects to preserve the complete schema structure.
93+ Uses a copy-then-normalize approach to preserve all original schema properties.
94+
6995 Args:
7096 schema: The schema to normalize.
7197
7298 Returns:
7399 The normalized schema.
74100 """
75- normalized = {"type" : schema .get ("type" , "object" ), "properties" : {}}
76-
77- # Handle properties
78- if "properties" in schema :
79- for prop_name , prop_def in schema ["properties" ].items ():
80- if isinstance (prop_def , dict ):
81- normalized_prop = {
82- "type" : prop_def .get ("type" , "string" ),
83- "description" : prop_def .get ("description" , f"Property { prop_name } " ),
84- }
85-
86- # Handle enum values correctly
87- if "enum" in prop_def :
88- normalized_prop ["enum" ] = prop_def ["enum" ]
89-
90- # Handle numeric constraints
91- if prop_def .get ("type" ) in ["number" , "integer" ]:
92- if "minimum" in prop_def :
93- normalized_prop ["minimum" ] = prop_def ["minimum" ]
94- if "maximum" in prop_def :
95- normalized_prop ["maximum" ] = prop_def ["maximum" ]
96-
97- normalized ["properties" ][prop_name ] = normalized_prop
98- else :
99- # Handle non-dict property definitions (like simple strings)
100- normalized ["properties" ][prop_name ] = {
101- "type" : "string" ,
102- "description" : f"Property { prop_name } " ,
103- }
104-
105- # Required fields
106- if "required" in schema :
107- normalized ["required" ] = schema ["required" ]
108- else :
109- normalized ["required" ] = []
101+ # Start with a complete copy to preserve all existing properties
102+ normalized = schema .copy ()
103+
104+ # Ensure essential structure exists
105+ normalized .setdefault ("type" , "object" )
106+ normalized .setdefault ("properties" , {})
107+ normalized .setdefault ("required" , [])
108+
109+ # Process properties recursively
110+ if "properties" in normalized :
111+ properties = normalized ["properties" ]
112+ for prop_name , prop_def in properties .items ():
113+ normalized ["properties" ][prop_name ] = _normalize_property (prop_name , prop_def )
110114
111115 return normalized
112116
0 commit comments