forked from strands-agents/sdk-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserializers.py
More file actions
150 lines (111 loc) · 4.02 KB
/
serializers.py
File metadata and controls
150 lines (111 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""State serializers for agent state management.
This module provides pluggable serialization strategies for AgentState:
- JSONSerializer: Default serializer, backward compatible, validates on set()
- PickleSerializer: Supports any Python object, no validation on set()
- StateSerializer: Protocol for custom serializers
"""
import copy
import json
import pickle
from typing import Any, Protocol, runtime_checkable
@runtime_checkable
class StateSerializer(Protocol):
"""Protocol for state serializers.
Custom serializers can implement this protocol to provide
alternative serialization strategies for agent state.
"""
def serialize(self, data: dict[str, Any]) -> bytes:
"""Serialize state dict to bytes.
Args:
data: Dictionary of state data to serialize
Returns:
Serialized state as bytes
"""
...
def deserialize(self, data: bytes) -> dict[str, Any]:
"""Deserialize bytes back to state dict.
Args:
data: Serialized state bytes
Returns:
Deserialized state dictionary
"""
...
def validate(self, value: Any) -> None:
"""Validate a value can be serialized.
Serializers that accept any value should implement this as a no-op.
Args:
value: The value to validate
Raises:
ValueError: If value cannot be serialized by this serializer
"""
...
class JSONSerializer:
"""JSON-based state serializer.
Default serializer that provides:
- Human-readable serialization format
- Validation on set() to maintain current behavior
- Backward compatibility with existing code
"""
def serialize(self, data: dict[str, Any]) -> bytes:
"""Serialize state dict to JSON bytes.
Args:
data: Dictionary of state data to serialize
Returns:
JSON serialized state as bytes
"""
return json.dumps(data).encode("utf-8")
def deserialize(self, data: bytes) -> dict[str, Any]:
"""Deserialize JSON bytes back to state dict.
Args:
data: JSON serialized state bytes
Returns:
Deserialized state dictionary
"""
result: dict[str, Any] = json.loads(data.decode("utf-8"))
return result
def validate(self, value: Any) -> None:
"""Validate that a value is JSON serializable.
Args:
value: The value to validate
Raises:
ValueError: If value is not JSON serializable
"""
try:
json.dumps(value)
except (TypeError, ValueError) as e:
raise ValueError(
f"Value is not JSON serializable: {type(value).__name__}. "
f"Only JSON-compatible types (str, int, float, bool, list, dict, None) are allowed."
) from e
class PickleSerializer:
"""Pickle-based state serializer.
Provides:
- Support for any Python object (datetime, UUID, dataclass, Pydantic models, etc.)
- No validation on set() (accepts anything)
Security Warning:
Pickle can execute arbitrary code during deserialization.
Only unpickle data from trusted sources.
"""
def serialize(self, data: dict[str, Any]) -> bytes:
"""Serialize state dict using pickle.
Args:
data: Dictionary of state data to serialize
Returns:
Pickle serialized state as bytes
"""
return pickle.dumps(copy.deepcopy(data))
def deserialize(self, data: bytes) -> dict[str, Any]:
"""Deserialize pickle bytes back to state dict.
Args:
data: Pickle serialized state bytes
Returns:
Deserialized state dictionary
"""
result: dict[str, Any] = pickle.loads(data) # noqa: S301
return result
def validate(self, value: Any) -> None:
"""No-op validation - pickle accepts any Python object.
Args:
value: The value to validate (ignored)
"""
pass