Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions deepgram/clients/agent/v1/websocket/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,30 @@ async def inject_user_message(self, options: InjectUserMessageOptions) -> bool:

return True

async def inject_agent_message(self, options: InjectAgentMessageOptions) -> bool:
"""
Injects an agent message to immediately trigger an agent statement.
"""
self._logger.spam("AsyncAgentWebSocketClient.inject_agent_message ENTER")

if not isinstance(options, InjectAgentMessageOptions):
self._logger.error("options must be of type InjectAgentMessageOptions")
self._logger.spam("AsyncAgentWebSocketClient.inject_agent_message LEAVE")
return False

self._logger.notice("Sending InjectAgentMessage...")
ret = await self.send(str(options))

if not ret:
self._logger.error("inject_agent_message failed")
self._logger.spam("AsyncAgentWebSocketClient.inject_agent_message LEAVE")
return False

self._logger.notice("inject_agent_message succeeded")
self._logger.spam("AsyncAgentWebSocketClient.inject_agent_message LEAVE")

return True

async def _close_message(self) -> bool:
# TODO: No known API close message # pylint: disable=fixme
# return await self.send(json.dumps({"type": "Close"}))
Expand Down
24 changes: 24 additions & 0 deletions deepgram/clients/agent/v1/websocket/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,30 @@ def inject_user_message(self, options: InjectUserMessageOptions) -> bool:

return True

def inject_agent_message(self, options: InjectAgentMessageOptions) -> bool:
"""
Injects an agent message to immediately trigger an agent statement.
"""
self._logger.spam("AgentWebSocketClient.inject_agent_message ENTER")

if not isinstance(options, InjectAgentMessageOptions):
self._logger.error("options must be of type InjectAgentMessageOptions")
self._logger.spam("AgentWebSocketClient.inject_agent_message LEAVE")
return False

self._logger.notice("Sending InjectAgentMessage...")
ret = self.send(str(options))

if not ret:
self._logger.error("inject_agent_message failed")
self._logger.spam("AgentWebSocketClient.inject_agent_message LEAVE")
return False

self._logger.notice("inject_agent_message succeeded")
self._logger.spam("AgentWebSocketClient.inject_agent_message LEAVE")

return True

def _close_message(self) -> bool:
# TODO: No known API close message # pylint: disable=fixme
# return self.send(json.dumps({"type": "Close"}))
Expand Down
200 changes: 200 additions & 0 deletions tests/unit_test/test_unit_agent_inject_agent_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import pytest
import json
from unittest.mock import patch, MagicMock

from deepgram import (
DeepgramClient,
InjectAgentMessageOptions,
)

class TestAgentInjectAgentMessage:
"""Focused unit tests for inject_agent_message functionality"""

def test_inject_agent_message_options_serialization(self):
"""Test JSON serialization is correct"""
options = InjectAgentMessageOptions(message="Test agent message")
result = json.loads(str(options))
expected = {"type": "InjectAgentMessage", "message": "Test agent message"}
assert result == expected

def test_inject_agent_message_options_default_message(self):
"""Test default empty message serialization"""
options = InjectAgentMessageOptions()
result = json.loads(str(options))
expected = {"type": "InjectAgentMessage", "message": ""}
assert result == expected

@patch('deepgram.clients.agent.v1.websocket.client.AgentWebSocketClient.send')
def test_inject_agent_message_success(self, mock_send):
"""Test successful message injection"""
mock_send.return_value = True

client = DeepgramClient("fake-key")
connection = client.agent.websocket.v("1")
options = InjectAgentMessageOptions(message="Hello from agent")

result = connection.inject_agent_message(options)

assert result == True
mock_send.assert_called_once_with(str(options))

@patch('deepgram.clients.agent.v1.websocket.client.AgentWebSocketClient.send')
def test_inject_agent_message_send_failure(self, mock_send):
"""Test handling of send method failure"""
mock_send.return_value = False

client = DeepgramClient("fake-key")
connection = client.agent.websocket.v("1")
options = InjectAgentMessageOptions(message="Hello from agent")

result = connection.inject_agent_message(options)

assert result == False
mock_send.assert_called_once_with(str(options))

def test_inject_agent_message_invalid_type(self):
"""Test error handling for invalid parameter type"""
client = DeepgramClient("fake-key")
connection = client.agent.websocket.v("1")

# Should return False for invalid type
result = connection.inject_agent_message("not an options object")
assert result == False

def test_inject_agent_message_none_parameter(self):
"""Test error handling for None parameter"""
client = DeepgramClient("fake-key")
connection = client.agent.websocket.v("1")

# Should return False for None parameter
result = connection.inject_agent_message(None)
assert result == False

def test_inject_agent_message_wrong_options_type(self):
"""Test error handling for wrong options type"""
from deepgram import InjectUserMessageOptions

client = DeepgramClient("fake-key")
connection = client.agent.websocket.v("1")

# Should return False for wrong options type
wrong_options = InjectUserMessageOptions(content="test")
result = connection.inject_agent_message(wrong_options)
assert result == False


class TestAsyncAgentInjectAgentMessage:
"""Focused unit tests for async inject_agent_message functionality"""

@pytest.mark.asyncio
@patch('deepgram.clients.agent.v1.websocket.async_client.AsyncAgentWebSocketClient.send')
async def test_async_inject_agent_message_success(self, mock_send):
"""Test successful async message injection"""
mock_send.return_value = True

client = DeepgramClient("fake-key")
connection = client.agent.asyncwebsocket.v("1")
options = InjectAgentMessageOptions(message="Hello from async agent")

result = await connection.inject_agent_message(options)

assert result == True
mock_send.assert_called_once_with(str(options))

@pytest.mark.asyncio
@patch('deepgram.clients.agent.v1.websocket.async_client.AsyncAgentWebSocketClient.send')
async def test_async_inject_agent_message_send_failure(self, mock_send):
"""Test handling of async send method failure"""
mock_send.return_value = False

client = DeepgramClient("fake-key")
connection = client.agent.asyncwebsocket.v("1")
options = InjectAgentMessageOptions(message="Hello from async agent")

result = await connection.inject_agent_message(options)

assert result == False
mock_send.assert_called_once_with(str(options))

@pytest.mark.asyncio
async def test_async_inject_agent_message_invalid_type(self):
"""Test error handling for invalid parameter type in async client"""
client = DeepgramClient("fake-key")
connection = client.agent.asyncwebsocket.v("1")

# Should return False for invalid type
result = await connection.inject_agent_message("not an options object")
assert result == False

@pytest.mark.asyncio
async def test_async_inject_agent_message_none_parameter(self):
"""Test error handling for None parameter in async client"""
client = DeepgramClient("fake-key")
connection = client.agent.asyncwebsocket.v("1")

# Should return False for None parameter
result = await connection.inject_agent_message(None)
assert result == False


class TestInjectAgentMessageIntegration:
"""Integration tests comparing inject_user_message and inject_agent_message"""

def test_options_classes_have_different_types(self):
"""Test that agent and user message options have different types"""
from deepgram import InjectUserMessageOptions

agent_options = InjectAgentMessageOptions(message="agent message")
user_options = InjectUserMessageOptions(content="user message")

agent_json = json.loads(str(agent_options))
user_json = json.loads(str(user_options))

assert agent_json["type"] == "InjectAgentMessage"
assert user_json["type"] == "InjectUserMessage"
assert agent_json["type"] != user_json["type"]

def test_options_classes_have_different_message_fields(self):
"""Test that agent and user message options have different field names"""
from deepgram import InjectUserMessageOptions

agent_options = InjectAgentMessageOptions(message="agent message")
user_options = InjectUserMessageOptions(content="user message")

agent_json = json.loads(str(agent_options))
user_json = json.loads(str(user_options))

# Agent uses 'message' field
assert "message" in agent_json
assert agent_json["message"] == "agent message"

# User uses 'content' field
assert "content" in user_json
assert user_json["content"] == "user message"

# They should not have each other's fields
assert "content" not in agent_json
assert "message" not in user_json

@patch('deepgram.clients.agent.v1.websocket.client.AgentWebSocketClient.send')
def test_both_injection_methods_exist(self, mock_send):
"""Test that both injection methods exist and are callable"""
from deepgram import InjectUserMessageOptions

mock_send.return_value = True

client = DeepgramClient("fake-key")
connection = client.agent.websocket.v("1")

# Test inject_user_message exists
user_options = InjectUserMessageOptions(content="user message")
user_result = connection.inject_user_message(user_options)
assert user_result == True

# Test inject_agent_message exists
agent_options = InjectAgentMessageOptions(message="agent message")
agent_result = connection.inject_agent_message(agent_options)
assert agent_result == True

# Both methods should have been called
assert mock_send.call_count == 2