Files
desklock/gateway/src/desklock_gateway/tatlock.py
T
jpmschweitzerandClaude Fable 5 576fd7d237 Initial scaffold: ESP32-P4 firmware + voice gateway for Tatlock endpoint
DeskLock gives the Tatlock butler a face and voice on a Waveshare
ESP32-P4-WIFI6-Touch-LCD-3.4C round display in the living room.

- firmware/: ESP-IDF project targeting esp32p4 with the Waveshare XC BSP
- gateway/: FastAPI voice bridge (faster-whisper STT, Tatlock chat, Piper TTS)
- docs/architecture.md: component design and device<->gateway WS protocol

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 16:58:59 +02:00

37 lines
1.2 KiB
Python

"""Client for the Tatlock butler's OpenAI-compatible chat API."""
import httpx
from .config import settings
class TatlockClient:
def __init__(self, base_url: str | None = None) -> None:
self._client = httpx.AsyncClient(
base_url=base_url or settings.tatlock_base_url,
timeout=httpx.Timeout(120.0, connect=5.0),
)
self._history: list[dict[str, str]] = []
async def ask(self, text: str) -> str:
"""Send one user utterance, return Tatlock's reply, keeping conversation history."""
self._history.append({"role": "user", "content": text})
response = await self._client.post(
"/v1/chat/completions",
json={
"model": settings.tatlock_model,
"messages": self._history,
"stream": False,
},
)
response.raise_for_status()
reply = response.json()["choices"][0]["message"]["content"]
self._history.append({"role": "assistant", "content": reply})
return reply
def reset(self) -> None:
self._history.clear()
async def aclose(self) -> None:
await self._client.aclose()