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

@@ -0,0 +1,132 @@
import asyncio
import threading
from types import SimpleNamespace
import pytest
from voice_assistant.agent.oci_connection import open_oci_stream
class FakeStream:
def __init__(self):
self.closed = False
def close(self):
self.closed = True
@pytest.mark.anyio
async def test_open_oci_stream_success():
stream = FakeStream()
response = SimpleNamespace(data=stream)
result = await open_oci_stream(lambda: response)
assert result is response
assert stream.closed is False
stream.close()
@pytest.mark.anyio
async def test_open_oci_stream_closes_late_response():
started = threading.Event()
release = threading.Event()
finished = threading.Event()
stream = FakeStream()
response = SimpleNamespace(data=stream)
def open_connection():
started.set()
release.wait(timeout=5.0)
try:
return response
finally:
finished.set()
task = asyncio.create_task(
open_oci_stream(open_connection)
)
try:
assert await asyncio.to_thread(
started.wait,
1.0,
)
task.cancel()
with pytest.raises(asyncio.CancelledError):
await task
finally:
release.set()
assert await asyncio.to_thread(
finished.wait,
1.0,
)
# The worker may still be completing its cleanup.
for _ in range(100):
if stream.closed:
break
await asyncio.sleep(0.001)
assert stream.closed is True
@pytest.mark.anyio
async def test_open_oci_stream_cancellation_during_handoff():
"""
Verify that a response is not abandoned when cancellation
happens around completion of the opening operation.
"""
stream = FakeStream()
response = SimpleNamespace(data=stream)
opened = threading.Event()
release = threading.Event()
def open_connection():
opened.set()
release.wait(timeout=5.0)
return response
task = asyncio.create_task(
open_oci_stream(open_connection)
)
try:
assert await asyncio.to_thread(
opened.wait,
1.0,
)
release.set()
task.cancel()
with pytest.raises(asyncio.CancelledError):
await task
for _ in range(100):
if stream.closed:
break
await asyncio.sleep(0.001)
assert stream.closed is True
finally:
release.set()
if not task.done():
task.cancel()
await asyncio.gather(
task,
return_exceptions=True,
)