@@ -132,11 +132,87 @@ function serializeToolInputSchema(value: unknown, path: string): RuntimeToolInpu
132132 } ;
133133 }
134134 return {
135- schema : parsed ,
135+ schema : normalizeProviderToolInputSchema ( parsed ) ,
136136 violations : [ ] ,
137137 } ;
138138}
139139
140+ function isNullSchema ( schema : RuntimeToolInputSchemaJson ) : boolean {
141+ return isJsonObject ( schema ) && schema . type === "null" ;
142+ }
143+
144+ function isStringConstSchema (
145+ schema : RuntimeToolInputSchemaJson ,
146+ ) : schema is { type : "string" ; const : string } {
147+ return isJsonObject ( schema ) && schema . type === "string" && typeof schema . const === "string" ;
148+ }
149+
150+ function mergeCompositionWrapper (
151+ wrapper : { [ key : string ] : RuntimeToolInputSchemaJson } ,
152+ replacement : { [ key : string ] : RuntimeToolInputSchemaJson } ,
153+ keyword : "anyOf" | "oneOf" ,
154+ ) : { [ key : string ] : RuntimeToolInputSchemaJson } {
155+ const { [ keyword ] : _composition , ...metadata } = wrapper ;
156+ return {
157+ ...replacement ,
158+ ...metadata ,
159+ } ;
160+ }
161+
162+ function normalizeSchemaComposition (
163+ schema : { [ key : string ] : RuntimeToolInputSchemaJson } ,
164+ keyword : "anyOf" | "oneOf" ,
165+ ) : { [ key : string ] : RuntimeToolInputSchemaJson } | undefined {
166+ const variants = schema [ keyword ] ;
167+ if ( ! Array . isArray ( variants ) ) {
168+ return undefined ;
169+ }
170+ const hasNullVariant = variants . some ( isNullSchema ) ;
171+ const nonNullVariants = variants . filter ( ( variant ) => ! isNullSchema ( variant ) ) ;
172+ if ( nonNullVariants . length === 0 ) {
173+ return undefined ;
174+ }
175+ if ( hasNullVariant && nonNullVariants . length === 1 && isJsonObject ( nonNullVariants [ 0 ] ) ) {
176+ return mergeCompositionWrapper ( schema , nonNullVariants [ 0 ] , keyword ) ;
177+ }
178+ if ( nonNullVariants . every ( isStringConstSchema ) ) {
179+ return mergeCompositionWrapper (
180+ schema ,
181+ {
182+ type : "string" ,
183+ enum : nonNullVariants . map ( ( variant ) => variant . const ) ,
184+ } ,
185+ keyword ,
186+ ) ;
187+ }
188+ const stringVariant = nonNullVariants . find (
189+ ( variant ) => isJsonObject ( variant ) && variant . type === "string" ,
190+ ) ;
191+ if ( stringVariant !== undefined && isJsonObject ( stringVariant ) ) {
192+ return mergeCompositionWrapper ( schema , stringVariant , keyword ) ;
193+ }
194+ return undefined ;
195+ }
196+
197+ function normalizeProviderToolInputSchema (
198+ schema : RuntimeToolInputSchemaJson ,
199+ ) : RuntimeToolInputSchemaJson {
200+ if ( Array . isArray ( schema ) ) {
201+ return schema . map ( normalizeProviderToolInputSchema ) ;
202+ }
203+ if ( ! isJsonObject ( schema ) ) {
204+ return schema ;
205+ }
206+ const normalized = Object . fromEntries (
207+ Object . entries ( schema ) . map ( ( [ key , value ] ) => [ key , normalizeProviderToolInputSchema ( value ) ] ) ,
208+ ) ;
209+ return (
210+ normalizeSchemaComposition ( normalized , "anyOf" ) ??
211+ normalizeSchemaComposition ( normalized , "oneOf" ) ??
212+ normalized
213+ ) ;
214+ }
215+
140216function findDynamicSchemaKeywordViolations (
141217 schema : RuntimeToolInputSchemaJson ,
142218 path : string ,
0 commit comments