Skip to content

Commit d54164e

Browse files
committed
move helper fn to utils
1 parent 8b33caa commit d54164e

File tree

2 files changed

+47
-46
lines changed

2 files changed

+47
-46
lines changed

python-sdk/ag_ui/core/utils.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from typing import Any
2+
3+
def make_json_safe(value: Any) -> Any:
4+
"""
5+
Recursively convert a value into a JSON-serializable structure.
6+
7+
- Handles Pydantic models via `model_dump`.
8+
- Handles LangChain messages via `to_dict`.
9+
- Recursively walks dicts, lists, and tuples.
10+
- For arbitrary objects, falls back to `__dict__` if available, else `repr()`.
11+
"""
12+
# Pydantic models
13+
if hasattr(value, "model_dump"):
14+
try:
15+
return make_json_safe(value.model_dump(by_alias=True, exclude_none=True))
16+
except Exception:
17+
pass
18+
19+
# LangChain-style objects
20+
if hasattr(value, "to_dict"):
21+
try:
22+
return make_json_safe(value.to_dict())
23+
except Exception:
24+
pass
25+
26+
# Dict
27+
if isinstance(value, dict):
28+
return {key: make_json_safe(sub_value) for key, sub_value in value.items()}
29+
30+
# List / tuple
31+
if isinstance(value, (list, tuple)):
32+
return [make_json_safe(sub_value) for sub_value in value]
33+
34+
# Already JSON safe
35+
if isinstance(value, (str, int, float, bool)) or value is None:
36+
return value
37+
38+
# Arbitrary object: try __dict__ first, fallback to repr
39+
if hasattr(value, "__dict__"):
40+
return {
41+
"__type__": type(value).__name__,
42+
**make_json_safe(value.__dict__),
43+
}
44+
45+
return repr(value)
Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
22
This module contains the EventEncoder class
33
"""
4-
from typing import Any
54
import json
65
from ag_ui.core.events import BaseEvent
6+
from ag_ui.core.utils import make_json_safe
77

88
AGUI_MEDIA_TYPE = "application/vnd.ag-ui.event+proto"
99

@@ -26,55 +26,11 @@ def encode(self, event: BaseEvent) -> str:
2626
"""
2727
return self._encode_sse(event)
2828

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-
7329
def _encode_sse(self, event: BaseEvent) -> str:
7430
"""
7531
Encodes an event into an SSE string.
7632
"""
7733
event_dict = event.model_dump(by_alias=True, exclude_none=True)
78-
json_ready = self.make_json_safe(event_dict)
34+
json_ready = make_json_safe(event_dict)
7935
json_string = json.dumps(json_ready)
8036
return f"data: {json_string}\n\n"

0 commit comments

Comments
 (0)