33import json
44import logging
55import typing
6+ from json .decoder import JSONDecodeError
67
8+ import websockets
79import websockets .sync .connection as websockets_sync_connection
810from ...core .events import EventEmitterMixin , EventType
911from ...core .unchecked_base_model import construct_type
3739 from websockets import WebSocketClientProtocol # type: ignore
3840
3941_logger = logging .getLogger (__name__ )
40-
41-
42- def _sanitize_numeric_types (obj : typing .Any ) -> typing .Any :
43- """
44- Recursively convert float values that are whole numbers to int.
45-
46- Workaround for Fern-generated models that type integer API fields
47- (like sample_rate) as float, causing JSON serialization to produce
48- values like 44100.0 instead of 44100. The Deepgram API rejects
49- float representations of integer fields.
50-
51- See: https://github.com/deepgram/internal-api-specs/issues/205
52- """
53- if isinstance (obj , dict ):
54- return {k : _sanitize_numeric_types (v ) for k , v in obj .items ()}
55- elif isinstance (obj , list ):
56- return [_sanitize_numeric_types (item ) for item in obj ]
57- elif isinstance (obj , float ) and obj .is_integer ():
58- return int (obj )
59- return obj
6042V1SocketClientResponse = typing .Union [
6143 AgentV1ReceiveFunctionCallResponse ,
6244 AgentV1PromptUpdated ,
@@ -88,7 +70,7 @@ async def __aiter__(self):
8870 yield message
8971 else :
9072 try :
91- yield construct_type (type_ = V1SocketClientResponse , object_ = json .loads (message )) # type: ignore
73+ yield construct_type (V1SocketClientResponse , json .loads (message )) # type: ignore
9274 except Exception :
9375 _logger .warning (
9476 "Skipping unknown WebSocket message; update your SDK version to support new message types."
@@ -113,14 +95,14 @@ async def start_listening(self):
11395 else :
11496 json_data = json .loads (raw_message )
11597 try :
116- parsed = construct_type (type_ = V1SocketClientResponse , object_ = json_data ) # type: ignore
98+ parsed = construct_type (V1SocketClientResponse , json_data ) # type: ignore
11799 except Exception :
118100 _logger .warning (
119101 "Skipping unknown WebSocket message; update your SDK version to support new message types."
120102 )
121103 continue
122104 await self ._emit_async (EventType .MESSAGE , parsed )
123- except Exception as exc :
105+ except ( websockets . WebSocketException , JSONDecodeError ) as exc :
124106 await self ._emit_async (EventType .ERROR , exc )
125107 finally :
126108 await self ._emit_async (EventType .CLOSE , None )
@@ -160,12 +142,12 @@ async def send_function_call_response(self, message: AgentV1SendFunctionCallResp
160142 """
161143 await self ._send_model (message )
162144
163- async def send_keep_alive (self , message : typing . Optional [ AgentV1KeepAlive ] = None ) -> None :
145+ async def send_keep_alive (self , message : AgentV1KeepAlive ) -> None :
164146 """
165147 Send a message to the websocket connection.
166148 The message will be sent as a AgentV1KeepAlive.
167149 """
168- await self ._send_model (message or AgentV1KeepAlive ( type = "KeepAlive" ) )
150+ await self ._send_model (message )
169151
170152 async def send_update_prompt (self , message : AgentV1UpdatePrompt ) -> None :
171153 """
@@ -197,7 +179,7 @@ async def recv(self) -> V1SocketClientResponse:
197179 return data # type: ignore
198180 json_data = json .loads (data )
199181 try :
200- return construct_type (type_ = V1SocketClientResponse , object_ = json_data ) # type: ignore
182+ return construct_type (V1SocketClientResponse , json_data ) # type: ignore
201183 except Exception :
202184 _logger .warning ("Skipping unknown WebSocket message; update your SDK version to support new message types." )
203185 return json_data # type: ignore
@@ -214,7 +196,7 @@ async def _send_model(self, data: typing.Any) -> None:
214196 """
215197 Send a Pydantic model to the websocket connection.
216198 """
217- await self ._send (_sanitize_numeric_types ( data .dict () ))
199+ await self ._send (data .dict ())
218200
219201
220202class V1SocketClient (EventEmitterMixin ):
@@ -228,7 +210,7 @@ def __iter__(self):
228210 yield message
229211 else :
230212 try :
231- yield construct_type (type_ = V1SocketClientResponse , object_ = json .loads (message )) # type: ignore
213+ yield construct_type (V1SocketClientResponse , json .loads (message )) # type: ignore
232214 except Exception :
233215 _logger .warning (
234216 "Skipping unknown WebSocket message; update your SDK version to support new message types."
@@ -253,14 +235,14 @@ def start_listening(self):
253235 else :
254236 json_data = json .loads (raw_message )
255237 try :
256- parsed = construct_type (type_ = V1SocketClientResponse , object_ = json_data ) # type: ignore
238+ parsed = construct_type (V1SocketClientResponse , json_data ) # type: ignore
257239 except Exception :
258240 _logger .warning (
259241 "Skipping unknown WebSocket message; update your SDK version to support new message types."
260242 )
261243 continue
262244 self ._emit (EventType .MESSAGE , parsed )
263- except Exception as exc :
245+ except ( websockets . WebSocketException , JSONDecodeError ) as exc :
264246 self ._emit (EventType .ERROR , exc )
265247 finally :
266248 self ._emit (EventType .CLOSE , None )
@@ -300,12 +282,12 @@ def send_function_call_response(self, message: AgentV1SendFunctionCallResponse)
300282 """
301283 self ._send_model (message )
302284
303- def send_keep_alive (self , message : typing . Optional [ AgentV1KeepAlive ] = None ) -> None :
285+ def send_keep_alive (self , message : AgentV1KeepAlive ) -> None :
304286 """
305287 Send a message to the websocket connection.
306288 The message will be sent as a AgentV1KeepAlive.
307289 """
308- self ._send_model (message or AgentV1KeepAlive ( type = "KeepAlive" ) )
290+ self ._send_model (message )
309291
310292 def send_update_prompt (self , message : AgentV1UpdatePrompt ) -> None :
311293 """
@@ -337,7 +319,7 @@ def recv(self) -> V1SocketClientResponse:
337319 return data # type: ignore
338320 json_data = json .loads (data )
339321 try :
340- return construct_type (type_ = V1SocketClientResponse , object_ = json_data ) # type: ignore
322+ return construct_type (V1SocketClientResponse , json_data ) # type: ignore
341323 except Exception :
342324 _logger .warning ("Skipping unknown WebSocket message; update your SDK version to support new message types." )
343325 return json_data # type: ignore
@@ -354,4 +336,4 @@ def _send_model(self, data: typing.Any) -> None:
354336 """
355337 Send a Pydantic model to the websocket connection.
356338 """
357- self ._send (_sanitize_numeric_types ( data .dict () ))
339+ self ._send (data .dict ())
0 commit comments