feat: integrate OCI agent streaming and web voice client

This commit is contained in:
2026-10-13 19:49:27 +00:00
parent 088473a0c8
commit 19a415daae
19 changed files with 2034 additions and 23 deletions

View File

@@ -1698,3 +1698,105 @@ def test_websocket_registration_failure_awaits_task_before_abort():
assert len(tasks) == 1
assert tasks[0].done()
assert abort_checked
def test_websocket_streaming_agent_and_tts():
"""
Verify streaming Agent text and TTS audio through WebSocket.
The first audio segment must be delivered before the
Agent's complete response.
"""
created_stt.clear()
class StreamingTestAgent:
async def stream(self, session_id, turn_id, text):
yield "Olá, como posso ajudar?"
yield " Estou à disposição."
class StreamingTestTTS:
async def synthesize(self, text):
yield text.encode("utf-8")
with patch.object(
main,
"create_agent_adapter",
return_value=StreamingTestAgent(),
):
with patch.object(
main,
"create_tts_adapter",
return_value=StreamingTestTTS(),
):
with client.websocket_connect("/ws/audio") as websocket:
websocket.send_json(
{
"type": "session.start",
"audio": {
"encoding": AUDIO_ENCODING,
"sample_rate": AUDIO_SAMPLE_RATE,
"channels": AUDIO_CHANNELS,
},
}
)
session_ready = websocket.receive_json()
assert session_ready["type"] == "session.ready"
websocket.send_json({"type": "audio.start"})
turn_started = websocket.receive_json()
assert turn_started["type"] == "turn.started"
turn_id = turn_started["turn_id"]
stt = created_stt[0]
stt.emit_final_now("Olá")
received_text = []
received_audio = []
received_complete_response = False
# The streaming path emits two deltas and
# two TTS audio segments.
for _ in range(20):
message = websocket.receive()
if message.get("bytes") is not None:
received_audio.append(message["bytes"])
else:
import json
event = json.loads(message["text"])
if event["type"] == "agent.delta":
received_text.append(event["text"])
elif event["type"] == "agent.response":
received_complete_response = True
elif event["type"] == "error":
raise AssertionError(
f"Gateway returned error: {event}"
)
if received_complete_response and len(received_audio) >= 2:
break
assert "".join(received_text) == (
"Olá, como posso ajudar?"
" Estou à disposição."
)
assert received_audio
assert received_complete_response
websocket.send_json(
{
"type": "audio.stop",
"turn_id": turn_id,
}
)
turn_ended = websocket.receive_json()
assert turn_ended["type"] == "turn.ended"