11"""
22This module contains the EventEncoder class
33"""
4-
4+ from typing import Any
5+ import json
56from ag_ui .core .events import BaseEvent
67
78AGUI_MEDIA_TYPE = "application/vnd.ag-ui.event+proto"
@@ -25,8 +26,55 @@ def encode(self, event: BaseEvent) -> str:
2526 """
2627 return self ._encode_sse (event )
2728
29+ def make_json_safe (self , value : Any ) -> Any :
30+ """
31+ Recursively convert a value into a JSON-serializable structure.
32+
33+ - Handles Pydantic models via `model_dump`.
34+ - Handles LangChain messages via `to_dict`.
35+ - Recursively walks dicts, lists, and tuples.
36+ - For arbitrary objects, falls back to `__dict__` if available, else `repr()`.
37+ """
38+ # Pydantic models
39+ if hasattr (value , "model_dump" ):
40+ try :
41+ return self .make_json_safe (value .model_dump (by_alias = True , exclude_none = True ))
42+ except Exception :
43+ pass
44+
45+ # LangChain-style objects
46+ if hasattr (value , "to_dict" ):
47+ try :
48+ return self .make_json_safe (value .to_dict ())
49+ except Exception :
50+ pass
51+
52+ # Dict
53+ if isinstance (value , dict ):
54+ return {key : self .make_json_safe (sub_value ) for key , sub_value in value .items ()}
55+
56+ # List / tuple
57+ if isinstance (value , (list , tuple )):
58+ return [self .make_json_safe (sub_value ) for sub_value in value ]
59+
60+ # Already JSON safe
61+ if isinstance (value , (str , int , float , bool )) or value is None :
62+ return value
63+
64+ # Arbitrary object: try __dict__ first, fallback to repr
65+ if hasattr (value , "__dict__" ):
66+ return {
67+ "__type__" : type (value ).__name__ ,
68+ ** self .make_json_safe (value .__dict__ ),
69+ }
70+
71+ return repr (value )
72+
2873 def _encode_sse (self , event : BaseEvent ) -> str :
2974 """
3075 Encodes an event into an SSE string.
3176 """
32- return f"data: { event .model_dump_json (by_alias = True , exclude_none = True )} \n \n "
77+ event_dict = event .model_dump (by_alias = True , exclude_none = True )
78+ json_ready = self .make_json_safe (event_dict )
79+ json_string = json .dumps (json_ready )
80+ return f"data: { json_string } \n \n "
0 commit comments