chore: clean imports and restore test coverage
This commit is contained in:
@@ -17,9 +17,6 @@ dependencies = [
|
|||||||
"websockets>=15.0.1,<16",
|
"websockets>=15.0.1,<16",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
|
||||||
voice-assistant = "voice_assistant:main"
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["uv_build>=0.12.17,<0.13.0"]
|
requires = ["uv_build>=0.12.17,<0.13.0"]
|
||||||
build-backend = "uv_build"
|
build-backend = "uv_build"
|
||||||
@@ -27,3 +24,8 @@ build-backend = "uv_build"
|
|||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
testpaths = ["tests"]
|
testpaths = ["tests"]
|
||||||
pythonpath = ["src"]
|
pythonpath = ["src"]
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = [
|
||||||
|
"ruff>=0.16.10",
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,2 +1,7 @@
|
|||||||
def main() -> None:
|
"""
|
||||||
print("Hello from voice-assistant!")
|
Voice Assistant package.
|
||||||
|
|
||||||
|
Provides realtime voice processing components, including
|
||||||
|
audio transport, speech recognition, agent orchestration,
|
||||||
|
speech synthesis, and turn lifecycle management.
|
||||||
|
"""
|
||||||
@@ -36,7 +36,6 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
||||||
from pydantic import BaseModel, ValidationError
|
from pydantic import BaseModel, ValidationError
|
||||||
import os
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@@ -45,7 +44,6 @@ from voice_assistant.stt.adapter import STTAdapter
|
|||||||
from voice_assistant.tts.adapter import TTSAdapter
|
from voice_assistant.tts.adapter import TTSAdapter
|
||||||
from voice_assistant.turn_manager import (
|
from voice_assistant.turn_manager import (
|
||||||
TurnManager,
|
TurnManager,
|
||||||
TurnState,
|
|
||||||
)
|
)
|
||||||
from voice_assistant.agent.adapter import AgentAdapter
|
from voice_assistant.agent.adapter import AgentAdapter
|
||||||
|
|
||||||
@@ -72,7 +70,6 @@ from voice_assistant.audio_gateway.app.protocol import (
|
|||||||
AUDIO_SAMPLE_RATE,
|
AUDIO_SAMPLE_RATE,
|
||||||
AUDIO_CHANNELS,
|
AUDIO_CHANNELS,
|
||||||
AudioChunk,
|
AudioChunk,
|
||||||
AudioStart,
|
|
||||||
AudioStop,
|
AudioStop,
|
||||||
Interrupt,
|
Interrupt,
|
||||||
SessionEnd,
|
SessionEnd,
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ from voice_assistant.config.models import (
|
|||||||
from voice_assistant.stt.adapter import STTAdapter
|
from voice_assistant.stt.adapter import STTAdapter
|
||||||
from voice_assistant.tts.adapter import TTSAdapter
|
from voice_assistant.tts.adapter import TTSAdapter
|
||||||
|
|
||||||
from voice_assistant.audio.models import CANONICAL_AUDIO_FORMAT
|
|
||||||
|
|
||||||
PROVIDER_CONTRACTS: dict[str, type] = {
|
PROVIDER_CONTRACTS: dict[str, type] = {
|
||||||
"stt": STTAdapter,
|
"stt": STTAdapter,
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ from voice_assistant.agent import MockAgentAdapter
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def text_mock_agent_process_text():
|
async def test_mock_agent_process_text():
|
||||||
agent = MackAgentAdapter()
|
"""
|
||||||
|
Verify that the mock Agent returns the expected response.
|
||||||
|
"""
|
||||||
|
agent = MockAgentAdapter()
|
||||||
|
|
||||||
response = await agent.process(
|
response = await agent.process(
|
||||||
session_id="session-1",
|
session_id="session-1",
|
||||||
@@ -21,15 +24,17 @@ async def text_mock_agent_process_text():
|
|||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def test_mock_agent_records_call():
|
async def test_mock_agent_records_call():
|
||||||
|
"""
|
||||||
|
Verify that the mock Agent records its invocation.
|
||||||
|
"""
|
||||||
agent = MockAgentAdapter()
|
agent = MockAgentAdapter()
|
||||||
|
|
||||||
await agent.process(
|
await agent.process(
|
||||||
session_id="session-1",
|
session_id="session-1",
|
||||||
turn_id=7,
|
turn_id=7,
|
||||||
text= "Olá",
|
text="Olá",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
assert agent.calls == [
|
assert agent.calls == [
|
||||||
(
|
(
|
||||||
"session-1",
|
"session-1",
|
||||||
@@ -37,4 +42,3 @@ async def test_mock_agent_records_call():
|
|||||||
"Olá",
|
"Olá",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ Architecture:
|
|||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from voice_assistant.config.loader import load_config
|
|
||||||
from voice_assistant.config.loader import (
|
from voice_assistant.config.loader import (
|
||||||
load_config,
|
load_config,
|
||||||
load_provider_catalog,
|
load_provider_catalog,
|
||||||
@@ -167,7 +166,7 @@ def test_load_provider_catalog_missing_file(tmp_path):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_load_config_uses_app_env(
|
def test_load_config_uses_development_app_env(
|
||||||
tmp_path,
|
tmp_path,
|
||||||
monkeypatch,
|
monkeypatch,
|
||||||
):
|
):
|
||||||
@@ -220,7 +219,7 @@ def test_load_config_rejects_unknown_environment(
|
|||||||
config_dir=tmp_path,
|
config_dir=tmp_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_load_config_uses_app_env(
|
def test_load_config_uses_staging_app_env(
|
||||||
tmp_path,
|
tmp_path,
|
||||||
monkeypatch,
|
monkeypatch,
|
||||||
):
|
):
|
||||||
@@ -273,16 +272,3 @@ agent:
|
|||||||
|
|
||||||
assert config.agent.provider == "mock"
|
assert config.agent.provider == "mock"
|
||||||
|
|
||||||
|
|
||||||
def test_load_config_rejects_unknown_environment(
|
|
||||||
tmp_path,
|
|
||||||
):
|
|
||||||
with pytest.raises(
|
|
||||||
FileNotFoundError,
|
|
||||||
match="Configuration file not found",
|
|
||||||
):
|
|
||||||
load_config(
|
|
||||||
environment="does-not-exist",
|
|
||||||
config_dir=tmp_path,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ from voice_assistant.audio_gateway.app.protocol import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Teste Agent
|
# Teste Agent
|
||||||
from voice_assistant.agent.adapter import AgentAdapter
|
|
||||||
from voice_assistant.agent.mock import MockAgentAdapter
|
from voice_assistant.agent.mock import MockAgentAdapter
|
||||||
|
|
||||||
# Teste TTS
|
# Teste TTS
|
||||||
|
|||||||
@@ -56,18 +56,6 @@ def test_cannot_start_second_turn():
|
|||||||
manager.start(2)
|
manager.start(2)
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_stop_before_completed():
|
|
||||||
manager = TurnManager()
|
|
||||||
|
|
||||||
manager.start(1)
|
|
||||||
|
|
||||||
with pytest.raises(
|
|
||||||
RuntimeError,
|
|
||||||
match="final transcript",
|
|
||||||
):
|
|
||||||
manager.stop(1)
|
|
||||||
|
|
||||||
|
|
||||||
def test_interrupt():
|
def test_interrupt():
|
||||||
manager = TurnManager()
|
manager = TurnManager()
|
||||||
|
|
||||||
@@ -152,7 +140,7 @@ def test_tts_completion_requires_speaking_state():
|
|||||||
manager.on_tts_complete(1)
|
manager.on_tts_complete(1)
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_stop_before_completed():
|
def test_cannot_stop_while_listening():
|
||||||
manager = TurnManager()
|
manager = TurnManager()
|
||||||
|
|
||||||
manager.start(1)
|
manager.start(1)
|
||||||
|
|||||||
33
uv.lock
generated
33
uv.lock
generated
@@ -1086,6 +1086,31 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruff"
|
||||||
|
version = "0.16.10"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c4/49/23802c45f093eb14bde54b141d2b2f058edfa63a06db7beed047308cc08f/ruff-0.16.10.tar.gz", hash = "sha256:eff4728c4eaae93f0955cd264d24b2ab348e74bf59986ccf282ba6dc16b3b017", size = 4958724, upload-time = "2026-10-01T18:03:21.697Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/21/ebce22e1d90cdb2cd691026b9c6e9bec6499f0b396089481755b5d49efff/ruff-0.16.10-py3-none-linux_armv6l.whl", hash = "sha256:488b0fe3f3574210e5cf80d9f59b9e3ab17a127a8155de3f307b392589cfb511", size = 10095557, upload-time = "2026-10-01T18:02:36.072Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/98/a54de85876a8b2612bfa0d84c7b9abfb39c6a3354aee7800b09c1649b9e3/ruff-0.16.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e748ff95c934c4e978783b8e687bc174e7bd84e8ad24e3243e1ecfcda5e0282d", size = 10340577, upload-time = "2026-10-01T18:02:39.258Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/16/1a5a4a2657effe4806110f2b907313802f1367fcdbb29e8122766e407fab/ruff-0.16.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3031a4a2e8e7b8a46f70be45f198c35a11ece509a94b80334d8d397a33c67550", size = 9774282, upload-time = "2026-10-01T18:02:41.79Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6e/fb/470085af734da396e68cd80fb0a3e7c109a459716ae59588c0f6fab8a17d/ruff-0.16.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:494401c86df4c4c25f69b9419605d944467ee98c42fb6ad405ef4fa40b8fb67d", size = 9920895, upload-time = "2026-10-01T18:02:44.458Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/57/de/f10cffe4f88a37ea6615ec460f01bf76f0bc1477737a35d9ee61a630a78b/ruff-0.16.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d203abc0ff2b773ee33d00ab8df0bb67046fbc7c07b119332f08b9b345cf8221", size = 9902707, upload-time = "2026-10-01T18:02:47.041Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/44/3fdcedf83ae60ef837dd239170e480dce606a9142cfa2db911afdf855fd9/ruff-0.16.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd83d1235a5258d318477bc5b576303974cbdef5df0c01a1bff14efcc23bd12a", size = 10619287, upload-time = "2026-10-01T18:02:49.485Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c1/62/02e76a5574002153618eafbb70e159468addc72a5d2c488e65cbb4639d2d/ruff-0.16.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc2610fb269fa56dd8a68669ae470fa6272902668c0fc2ebc3aa112b2633d5b8", size = 11339942, upload-time = "2026-10-01T18:02:52.008Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/c4/cde27d47ad8d4126c587e608c67c46e7feac11763f606d261a1bc8a489e6/ruff-0.16.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e70175e29cc94c26ea296c80e470180b744b7419026898e58f520c6ab32578e", size = 10934316, upload-time = "2026-10-01T18:02:54.811Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/03/17234145f302a645a123e8c3bb2411ecf4669fbc350de3b0d803230a1729/ruff-0.16.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f33f43a864a8483eebd160e713336c8bab02c934feaff0a33cf5ccb41546d09a", size = 10387968, upload-time = "2026-10-01T18:02:57.497Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/71/29/2493af60240ee7644b38a4b821f5f9c3b5a4fa3178770fe1d0c685217395/ruff-0.16.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1dfc6f0088149fb6a362c1c446bcbb3fd2157b3852fe2fa68409276eab9ad9b3", size = 10537906, upload-time = "2026-10-01T18:03:00.006Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/9a/f56b28f3b143bb9e518c34fb89ab191b626bca8b70dbf8af0d2e2d473572/ruff-0.16.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6553498afc35f580f036030795810b9e6bcea31604b0fd9e8d352795473042e3", size = 10012938, upload-time = "2026-10-01T18:03:03.006Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/c4/fca37362848ea4d4d80712df13632e645e7c7cfb1bdedf140699ac7a090b/ruff-0.16.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a3b8471dea115d37f123882be852bed13403746d3a76c11de4a19ec5f9ff5a03", size = 9897945, upload-time = "2026-10-01T18:03:05.818Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7d/c7/e0bc57664d6e0c61fd22f620af260fe9662d7e1ddb320ea7f160e76ef165/ruff-0.16.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:92e59a70bcbd9d3a5483656da906ec28edfdacfce00afd99edb8b4e9d15644be", size = 10333134, upload-time = "2026-10-01T18:03:08.25Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/21/aa/5c9f3b68737c0e4a33a1db5dfab44f7b786d96ca91a7233112ddab1e6dc2/ruff-0.16.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7ae7375f803b5520dc9f546bed7e3a0acb70b91812e9bb4b19927de22f25b77d", size = 10741702, upload-time = "2026-10-01T18:03:10.775Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/fa/0f9c2020dc316c53d983be011720b8157cc052b97e3f4dfa7db6d0f880a6/ruff-0.16.10-py3-none-win32.whl", hash = "sha256:2a12e01cb9156c10c466f63b46eaae5ecea28dfbd21b5836353ae498e7d1349a", size = 10139176, upload-time = "2026-10-01T18:03:13.267Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/99/29/cfb0df9448d4d4ad48c2de029ada9ebd71baa6da983a6c77ee6c6cd0fe82/ruff-0.16.10-py3-none-win_amd64.whl", hash = "sha256:97f2015c92aa97105b0eab19eb5d224884399281cfc5da86a92db4ab5e7fb2ca", size = 10584734, upload-time = "2026-10-01T18:03:16.006Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fc/05/c16957eb287c3fc062e032619a25868d93d408a844b725bcf514f7a378ff/ruff-0.16.10-py3-none-win_arm64.whl", hash = "sha256:25a65fe998c4e6861ec079ada5826a2fc605e6cbccbe9dcd7fac1f54e791621b", size = 10366440, upload-time = "2026-10-01T18:03:19.04Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "84.0.0"
|
version = "84.0.0"
|
||||||
@@ -1268,6 +1293,11 @@ dependencies = [
|
|||||||
{ name = "websockets" },
|
{ name = "websockets" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.dev-dependencies]
|
||||||
|
dev = [
|
||||||
|
{ name = "ruff" },
|
||||||
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "fastapi", specifier = ">=0.141.1" },
|
{ name = "fastapi", specifier = ">=0.141.1" },
|
||||||
@@ -1282,6 +1312,9 @@ requires-dist = [
|
|||||||
{ name = "websockets", specifier = ">=15.0.1,<16" },
|
{ name = "websockets", specifier = ">=15.0.1,<16" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.metadata.requires-dev]
|
||||||
|
dev = [{ name = "ruff", specifier = ">=0.16.10" }]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "watchfiles"
|
name = "watchfiles"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user