Skip to content

fix(websockets): restore optional message param on control send_ methods#680

Merged
lukeocodes merged 2 commits intomainfrom
fix/websocket-optional-control-message-params
Mar 27, 2026
Merged

fix(websockets): restore optional message param on control send_ methods#680
lukeocodes merged 2 commits intomainfrom
fix/websocket-optional-control-message-params

Conversation

@lukeocodes
Copy link
Copy Markdown
Member

Summary

  • Control send_ methods (send_keep_alive, send_close_stream, send_finalize, send_flush, send_clear, send_close) lost their optional message parameter in the last regen
  • This shipped as a breaking change in a minor patch — callers using send_keep_alive() etc. without args started getting TypeError
  • Restores message: Optional[T] = None with a typed default on all control methods across all 4 WebSocket clients
  • Payload-carrying methods (send_text, send_media, send_settings, etc.) remain required

Affected files

  • src/deepgram/speak/v1/socket_client.pysend_flush, send_clear, send_close
  • src/deepgram/listen/v1/socket_client.pysend_finalize, send_close_stream, send_keep_alive
  • src/deepgram/listen/v2/socket_client.pysend_close_stream
  • src/deepgram/agent/v1/socket_client.pysend_keep_alive
  • .fernignore — updated comment to document this patch

Test plan

  • Verify send_keep_alive(), send_close_stream(), send_finalize(), send_flush(), send_clear(), send_close() can be called with no arguments
  • Verify passing an explicit message object still works
  • pytest passes

Control messages (keep-alive, close-stream, finalize, flush, clear, close)
carry no meaningful payload — the type field is the whole message. Making
the message param optional with a typed default means users can call e.g.
send_keep_alive() without constructing the type themselves.

Payload-carrying methods (send_text, send_media, send_settings, etc.) remain
required. This restores behaviour lost in the last regen and fixes a breaking
change shipped in a minor patch.
Copilot AI review requested due to automatic review settings March 27, 2026 19:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restores backward-compatible WebSocket control send_* method signatures by reintroducing an optional message parameter (defaulting to None) and constructing a default control payload when omitted, avoiding TypeError regressions from the last regen.

Changes:

  • Make control send_* methods accept message: Optional[T] = None across Speak v1, Listen v1/v2, and Agent v1 socket clients.
  • When message is omitted, send a default control model instance (e.g., type="CloseStream").
  • Document the generator freeze rationale in .fernignore with an added note about this patch.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/deepgram/speak/v1/socket_client.py Restores optional params for send_flush/send_clear/send_close and sends default typed control messages when omitted.
src/deepgram/listen/v1/socket_client.py Restores optional params for send_finalize/send_close_stream/send_keep_alive and sends default typed control messages when omitted.
src/deepgram/listen/v2/socket_client.py Restores optional param for send_close_stream and sends a default typed control message when omitted.
src/deepgram/agent/v1/socket_client.py Restores optional param for send_keep_alive and attempts to send a default keep-alive message when omitted.
.fernignore Adds a comment documenting this patch as part of the generator freeze notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The message will be sent as a AgentV1KeepAlive.
"""
await self._send_model(message)
await self._send_model(message or AgentV1KeepAlive())
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AgentV1KeepAlive requires a type field (no default in the model), so AgentV1KeepAlive() will raise a validation error. This means send_keep_alive() is still not callable with no args. Construct the default message with the required type (e.g., the "KeepAlive" literal) when message is omitted.

Suggested change
await self._send_model(message or AgentV1KeepAlive())
if message is None:
message = AgentV1KeepAlive(type="KeepAlive")
await self._send_model(message)

Copilot uses AI. Check for mistakes.
The message will be sent as a AgentV1KeepAlive.
"""
self._send_model(message)
self._send_model(message or AgentV1KeepAlive())
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue for the sync client: AgentV1KeepAlive() is missing the required type field, so this default will raise at runtime. Please set the type field when constructing the default keep-alive message.

Suggested change
self._send_model(message or AgentV1KeepAlive())
self._send_model(message or AgentV1KeepAlive(type="keep_alive"))

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +103
async def send_finalize(self, message: typing.Optional[ListenV1Finalize] = None) -> None:
"""
Send a message to the websocket connection.
The message will be sent as a ListenV1Finalize.
"""
await self._send_model(message)
await self._send_model(message or ListenV1Finalize(type="Finalize"))

async def send_close_stream(self, message: ListenV1CloseStream) -> None:
async def send_close_stream(self, message: typing.Optional[ListenV1CloseStream] = None) -> None:
"""
Send a message to the websocket connection.
The message will be sent as a ListenV1CloseStream.
"""
await self._send_model(message)
await self._send_model(message or ListenV1CloseStream(type="CloseStream"))

async def send_keep_alive(self, message: ListenV1KeepAlive) -> None:
async def send_keep_alive(self, message: typing.Optional[ListenV1KeepAlive] = None) -> None:
"""
Send a message to the websocket connection.
The message will be sent as a ListenV1KeepAlive.
"""
await self._send_model(message)
await self._send_model(message or ListenV1KeepAlive(type="KeepAlive"))
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR restores optional control-message params, but there are no tests asserting that these send_*() control methods can be called with no arguments (and that they send the expected default payload). Since the repo already has coverage for listen.v1.socket_client behavior in tests/custom/test_transport.py, please add a small unit test that instantiates the socket client with a mock transport and verifies send_keep_alive()/send_close_stream()/send_finalize() work without args.

Copilot uses AI. Check for mistakes.
Also fixes AgentV1KeepAlive default to include type='KeepAlive' (bare
AgentV1KeepAlive() fails Pydantic validation since type is required).
@lukeocodes lukeocodes merged commit 0018fc4 into main Mar 27, 2026
14 checks passed
@lukeocodes lukeocodes deleted the fix/websocket-optional-control-message-params branch March 27, 2026 19:55
@lukeocodes lukeocodes linked an issue Mar 27, 2026 that may be closed by this pull request
2 tasks
lukeocodes pushed a commit that referenced this pull request Mar 27, 2026
🤖 I have created a release *beep* *boop*
---


##
[6.1.1](v6.1.0...v6.1.1)
(2026-03-27)


### Bug Fixes

* **websockets:** restore optional message param on control send_
methods
([#680](#680))
([0018fc4](0018fc4))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: TTS: SpeakV1Text() type is broken in v6.1.0

3 participants