@@ -227,6 +227,52 @@ def validate_message(
227227 ) from e
228228
229229
230+ def _validate_against_types (
231+ data : dict [str , Any ],
232+ model_types : tuple [type [BaseModel ], ...],
233+ category_name : str ,
234+ ) -> BaseModel :
235+ """Validate data against multiple model types and return first match.
236+
237+ Args:
238+ data: Raw data to validate.
239+ model_types: Tuple of model types to try.
240+ category_name: Name of the category for error messages (e.g., 'request', 'response').
241+
242+ Returns:
243+ The validated model instance.
244+
245+ Raises:
246+ ValidationError: If data doesn't match any of the provided types.
247+ """
248+ errors : list [dict [str , Any ]] = []
249+
250+ for model_type in model_types :
251+ try :
252+ return validate_message (data , model_type , strict = False )
253+ except ValidationError as e :
254+ errors .append (
255+ {
256+ 'type' : model_type .__name__ ,
257+ 'path' : e .errors [0 ].get ('path' , []) if e .errors else [],
258+ 'message' : e .errors [0 ].get ('message' , str (e ))
259+ if e .errors
260+ else str (e ),
261+ }
262+ )
263+
264+ error_details = '; ' .join (
265+ f'{ e ["type" ]} : { e ["message" ]} (path: { "." .join (map (str , e ["path" ])) or "root" } )'
266+ for e in errors
267+ )
268+ raise ValidationError (
269+ f'Data does not match any known A2A { category_name } type. '
270+ f'Attempted types: { [e ["type" ] for e in errors ]} . Details: { error_details } ' ,
271+ errors = errors ,
272+ instance = data ,
273+ )
274+
275+
230276def validate_request (data : dict [str , Any ]) -> BaseModel :
231277 """Validate and parse an A2A request message.
232278
@@ -252,33 +298,7 @@ def validate_request(data: dict[str, Any]) -> BaseModel:
252298 TaskResubscriptionRequest ,
253299 )
254300
255- errors : list [dict [str , Any ]] = []
256-
257- for model_type in request_types :
258- try :
259- return validate_message (data , model_type , strict = False )
260- except ValidationError :
261- continue
262-
263- raise ValidationError (
264- 'Data does not match any known A2A request type' ,
265- errors = errors ,
266- instance = data ,
267- )
268-
269- errors : list [dict [str , Any ]] = []
270-
271- for model_type in request_types :
272- try :
273- return validate_message (data , model_type , strict = False )
274- except ValidationError :
275- continue
276-
277- raise ValidationError (
278- 'Data does not match any known A2A request type' ,
279- errors = errors ,
280- instance = data ,
281- )
301+ return _validate_against_types (data , request_types , 'request' )
282302
283303
284304def validate_response (data : dict [str , Any ]) -> BaseModel :
@@ -302,27 +322,7 @@ def validate_response(data: dict[str, Any]) -> BaseModel:
302322 GetTaskPushNotificationConfigResponse ,
303323 )
304324
305- for model_type in response_types :
306- try :
307- return validate_message (data , model_type , strict = False )
308- except ValidationError :
309- continue
310-
311- raise ValidationError (
312- 'Data does not match any known A2A response type' ,
313- instance = data ,
314- )
315-
316- for model_type in response_types :
317- try :
318- return validate_message (data , model_type , strict = False )
319- except ValidationError :
320- continue
321-
322- raise ValidationError (
323- 'Data does not match any known A2A response type' ,
324- instance = data ,
325- )
325+ return _validate_against_types (data , response_types , 'response' )
326326
327327
328328class MessageValidator :
0 commit comments