fix: tts endpoints

This commit is contained in:
Brooklyn Nicholson
2026-05-30 19:35:34 -05:00
parent fd88dd96a9
commit dfc2fd887e
2 changed files with 217 additions and 3 deletions
+85
View File
@@ -174,6 +174,37 @@ class TestWebServerEndpoints:
row = next(s for s in rows if s["id"] == "session-no-cwd")
assert row["cwd"] is None
def test_get_sessions_forwards_min_messages(self, monkeypatch):
"""The ?min_messages= filter must reach SessionDB.
The desktop session picker calls /api/sessions?...&min_messages=N to
hide empty sessions. The param was silently dropped from the handler
in a merge once (SessionDB still supported it); guard the wiring.
"""
captured = {}
class _FakeDB:
def __init__(self, *args, **kwargs):
pass
def list_sessions_rich(self, limit, offset, min_message_count=0):
captured["list"] = min_message_count
return []
def session_count(self, min_message_count=0):
captured["count"] = min_message_count
return 0
def close(self):
pass
monkeypatch.setattr("hermes_state.SessionDB", _FakeDB)
resp = self.client.get("/api/sessions?limit=5&offset=0&min_messages=3")
assert resp.status_code == 200
assert captured["list"] == 3
assert captured["count"] == 3
def test_audio_transcription_endpoint(self, monkeypatch):
import tools.transcription_tools as transcription_tools
@@ -218,6 +249,60 @@ class TestWebServerEndpoints:
assert resp.status_code == 400
assert "base64" in resp.json()["detail"]
def test_desktop_audio_routes_registered(self):
"""All three desktop voice endpoints must exist.
The renderer (apps/desktop) calls /api/audio/transcribe, /speak, and
/elevenlabs/voices. /speak + /voices were silently dropped in a merge
once; this guards the contract so a future merge can't lose them
without failing CI.
"""
from hermes_cli.web_server import app
paths = {getattr(r, "path", None) for r in app.routes}
assert "/api/audio/transcribe" in paths
assert "/api/audio/speak" in paths
assert "/api/audio/elevenlabs/voices" in paths
def test_elevenlabs_voices_unavailable_without_key(self, monkeypatch):
import hermes_cli.web_server as web_server
monkeypatch.setattr(web_server, "load_env", lambda: {})
monkeypatch.delenv("ELEVENLABS_API_KEY", raising=False)
resp = self.client.get("/api/audio/elevenlabs/voices")
assert resp.status_code == 200
assert resp.json() == {"available": False, "voices": []}
def test_speak_text_returns_base64_data_url(self, monkeypatch, tmp_path):
import tools.tts_tool as tts_tool
audio_file = tmp_path / "speech.mp3"
audio_file.write_bytes(b"ID3fake-audio-bytes")
def fake_tts(text):
return json.dumps({
"success": True,
"file_path": str(audio_file),
"provider": "test",
})
monkeypatch.setattr(tts_tool, "text_to_speech_tool", fake_tts)
resp = self.client.post("/api/audio/speak", json={"text": "hello there"})
assert resp.status_code == 200
body = resp.json()
assert body["ok"] is True
assert body["mime_type"] == "audio/mpeg"
assert body["data_url"].startswith("data:audio/mpeg;base64,")
assert body["provider"] == "test"
# The handler streams the bytes back and removes the temp file.
assert not audio_file.exists()
def test_speak_text_requires_nonempty_text(self):
resp = self.client.post("/api/audio/speak", json={"text": " "})
assert resp.status_code == 400
def test_get_status_filters_unconfigured_gateway_platforms(self, monkeypatch):
import gateway.config as gateway_config
import hermes_cli.web_server as web_server