Skip to content

Commit dde19d3

Browse files
committed
chore: re-apply manual patches after regen
This covers: re-applied socket client patches (construct_type keyword args, broad exception catch, optional send_ params, _sanitize_numeric_types), removed .bak files, restored .fernignore, dropped type file freezes (generator now correct), fixed wiremock date format.
1 parent 37c9e23 commit dde19d3

13 files changed

Lines changed: 93 additions & 1214 deletions

.fernignore

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,10 @@ src/deepgram/client.py
1111
# - optional message param on control send_ methods (send_keep_alive, send_close_stream, etc.)
1212
# so users don't need to instantiate the type themselves for no-payload control messages
1313
# [temporarily frozen — generator bugs in construct_type call convention and exception handling]
14-
src/deepgram/agent/v1/socket_client.py.bak
15-
src/deepgram/listen/v1/socket_client.py.bak
16-
src/deepgram/listen/v2/socket_client.py.bak
17-
src/deepgram/speak/v1/socket_client.py.bak
18-
19-
# Type files with manual int type corrections (Fern generates float for speaker/channel/num_words)
20-
# [temporarily frozen — waiting on internal-api-specs#205]
21-
src/deepgram/types/listen_v1response_results_utterances_item.py.bak
22-
src/deepgram/types/listen_v1response_results_utterances_item_words_item.py.bak
23-
src/deepgram/types/listen_v1response_results_channels_item_alternatives_item_paragraphs_paragraphs_item.py.bak
14+
src/deepgram/agent/v1/socket_client.py
15+
src/deepgram/listen/v1/socket_client.py
16+
src/deepgram/listen/v2/socket_client.py
17+
src/deepgram/speak/v1/socket_client.py
2418

2519
# Hand-written custom tests
2620
tests/custom/test_text_builder.py

src/deepgram/agent/v1/socket_client.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
import json
44
import logging
55
import typing
6-
from json.decoder import JSONDecodeError
76

8-
import websockets
97
import websockets.sync.connection as websockets_sync_connection
108
from ...core.events import EventEmitterMixin, EventType
119
from ...core.unchecked_base_model import construct_type
@@ -39,6 +37,28 @@
3937
from websockets import WebSocketClientProtocol # type: ignore
4038

4139
_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
60+
61+
4262
V1SocketClientResponse = typing.Union[
4363
AgentV1ReceiveFunctionCallResponse,
4464
AgentV1PromptUpdated,
@@ -70,7 +90,7 @@ async def __aiter__(self):
7090
yield message
7191
else:
7292
try:
73-
yield construct_type(V1SocketClientResponse, json.loads(message)) # type: ignore
93+
yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore
7494
except Exception:
7595
_logger.warning(
7696
"Skipping unknown WebSocket message; update your SDK version to support new message types."
@@ -95,14 +115,14 @@ async def start_listening(self):
95115
else:
96116
json_data = json.loads(raw_message)
97117
try:
98-
parsed = construct_type(V1SocketClientResponse, json_data) # type: ignore
118+
parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore
99119
except Exception:
100120
_logger.warning(
101121
"Skipping unknown WebSocket message; update your SDK version to support new message types."
102122
)
103123
continue
104124
await self._emit_async(EventType.MESSAGE, parsed)
105-
except (websockets.WebSocketException, JSONDecodeError) as exc:
125+
except Exception as exc:
106126
await self._emit_async(EventType.ERROR, exc)
107127
finally:
108128
await self._emit_async(EventType.CLOSE, None)
@@ -142,12 +162,12 @@ async def send_function_call_response(self, message: AgentV1SendFunctionCallResp
142162
"""
143163
await self._send_model(message)
144164

145-
async def send_keep_alive(self, message: AgentV1KeepAlive) -> None:
165+
async def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None:
146166
"""
147167
Send a message to the websocket connection.
148168
The message will be sent as a AgentV1KeepAlive.
149169
"""
150-
await self._send_model(message)
170+
await self._send_model(message or AgentV1KeepAlive(type="KeepAlive"))
151171

152172
async def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None:
153173
"""
@@ -179,7 +199,7 @@ async def recv(self) -> V1SocketClientResponse:
179199
return data # type: ignore
180200
json_data = json.loads(data)
181201
try:
182-
return construct_type(V1SocketClientResponse, json_data) # type: ignore
202+
return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore
183203
except Exception:
184204
_logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.")
185205
return json_data # type: ignore
@@ -196,7 +216,7 @@ async def _send_model(self, data: typing.Any) -> None:
196216
"""
197217
Send a Pydantic model to the websocket connection.
198218
"""
199-
await self._send(data.dict())
219+
await self._send(_sanitize_numeric_types(data.dict()))
200220

201221

202222
class V1SocketClient(EventEmitterMixin):
@@ -210,7 +230,7 @@ def __iter__(self):
210230
yield message
211231
else:
212232
try:
213-
yield construct_type(V1SocketClientResponse, json.loads(message)) # type: ignore
233+
yield construct_type(type_=V1SocketClientResponse, object_=json.loads(message)) # type: ignore
214234
except Exception:
215235
_logger.warning(
216236
"Skipping unknown WebSocket message; update your SDK version to support new message types."
@@ -235,14 +255,14 @@ def start_listening(self):
235255
else:
236256
json_data = json.loads(raw_message)
237257
try:
238-
parsed = construct_type(V1SocketClientResponse, json_data) # type: ignore
258+
parsed = construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore
239259
except Exception:
240260
_logger.warning(
241261
"Skipping unknown WebSocket message; update your SDK version to support new message types."
242262
)
243263
continue
244264
self._emit(EventType.MESSAGE, parsed)
245-
except (websockets.WebSocketException, JSONDecodeError) as exc:
265+
except Exception as exc:
246266
self._emit(EventType.ERROR, exc)
247267
finally:
248268
self._emit(EventType.CLOSE, None)
@@ -282,12 +302,12 @@ def send_function_call_response(self, message: AgentV1SendFunctionCallResponse)
282302
"""
283303
self._send_model(message)
284304

285-
def send_keep_alive(self, message: AgentV1KeepAlive) -> None:
305+
def send_keep_alive(self, message: typing.Optional[AgentV1KeepAlive] = None) -> None:
286306
"""
287307
Send a message to the websocket connection.
288308
The message will be sent as a AgentV1KeepAlive.
289309
"""
290-
self._send_model(message)
310+
self._send_model(message or AgentV1KeepAlive(type="KeepAlive"))
291311

292312
def send_update_prompt(self, message: AgentV1UpdatePrompt) -> None:
293313
"""
@@ -319,7 +339,7 @@ def recv(self) -> V1SocketClientResponse:
319339
return data # type: ignore
320340
json_data = json.loads(data)
321341
try:
322-
return construct_type(V1SocketClientResponse, json_data) # type: ignore
342+
return construct_type(type_=V1SocketClientResponse, object_=json_data) # type: ignore
323343
except Exception:
324344
_logger.warning("Skipping unknown WebSocket message; update your SDK version to support new message types.")
325345
return json_data # type: ignore
@@ -336,4 +356,4 @@ def _send_model(self, data: typing.Any) -> None:
336356
"""
337357
Send a Pydantic model to the websocket connection.
338358
"""
339-
self._send(data.dict())
359+
self._send(_sanitize_numeric_types(data.dict()))

0 commit comments

Comments
 (0)