feat(llm): speech-to-text for patient voice input via OpenRouter (+ offline mock)
CI / ruff · pytest (pull_request) Successful in 2m57s

POST /api/v1/me/{token}/stt takes a 16 kHz mono WAV and only transcribes:
the patient checks the text and sends it as an ordinary message, so safety,
scrub() and the LLM gateway still apply. Audio is neither stored nor logged.
OpenRouter STT is synthetic-data only (ADR-014); SaluteSpeech for the pilot is #121.

Refs #116

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 11:19:55 +03:00
co-authored by Claude Opus 5.5
parent 4b166cf488
commit 7443b61974
9 changed files with 430 additions and 4 deletions
+2 -2
View File
@@ -267,9 +267,9 @@ async def test_connect_care_does_not_reassign_or_create_patients(client: AsyncCl
async def test_screening_capability_respects_release_gate(client: AsyncClient, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("INTAKE_DEMO", "0")
assert (await client.get("/api/v1/patient/capabilities")).json() == {"primary_screening": False}
assert (await client.get("/api/v1/patient/capabilities")).json()["primary_screening"] is False
monkeypatch.setenv("INTAKE_DEMO", "1")
assert (await client.get("/api/v1/patient/capabilities")).json() == {"primary_screening": True}
assert (await client.get("/api/v1/patient/capabilities")).json()["primary_screening"] is True
async def test_anonymous_contact_request_reaches_doctor(client: AsyncClient, monkeypatch: pytest.MonkeyPatch) -> None: