move signal bot to its own DB

This commit is contained in:
2026-03-18 08:35:45 -04:00
parent 2661127426
commit 976c3f9d3e
15 changed files with 402 additions and 52 deletions

View File

@@ -2,6 +2,7 @@
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any
import requests
@@ -10,11 +11,15 @@ if TYPE_CHECKING:
from python.signal_bot.models import SignalMessage
from python.signal_bot.signal_client import SignalClient
logger = logging.getLogger(__name__)
def _get_entity_state(ha_url: str, ha_token: str, entity_id: str) -> dict[str, Any]:
"""Fetch an entity's state from Home Assistant."""
entity_url = f"{ha_url}/api/states/{entity_id}"
logger.debug(f"Fetching {entity_url=}")
response = requests.get(
f"{ha_url}/api/states/{entity_id}",
entity_url,
headers={"Authorization": f"Bearer {ha_token}"},
timeout=30,
)
@@ -24,10 +29,7 @@ def _get_entity_state(ha_url: str, ha_token: str, entity_id: str) -> dict[str, A
def _format_location(latitude: str, longitude: str) -> str:
"""Render a friendly location response."""
return (
f"Van location: {latitude}, {longitude}\n"
f"https://maps.google.com/?q={latitude},{longitude}"
)
return f"Van location: {latitude}, {longitude}\nhttps://maps.google.com/?q={latitude},{longitude}"
def handle_location_request(
@@ -41,10 +43,14 @@ def handle_location_request(
signal.reply(message, "Location command is not configured (missing HA_URL or HA_TOKEN).")
return
lat_payload = None
lon_payload = None
try:
lat_payload = _get_entity_state(ha_url, ha_token, "sensor.van_last_known_latitude")
lon_payload = _get_entity_state(ha_url, ha_token, "sensor.van_last_known_longitude")
except requests.RequestException:
logger.exception("Couldn't fetch van location from Home Assistant right now.")
logger.debug(f"{ha_url=} {lat_payload=} {lon_payload=}")
signal.reply(message, "Couldn't fetch van location from Home Assistant right now.")
return

View File

@@ -10,7 +10,7 @@ from sqlalchemy import delete, select
from sqlalchemy.orm import Session
from python.common import utcnow
from python.orm.richie.signal_device import RoleRecord, SignalDevice
from python.orm.signal_bot.models import RoleRecord, SignalDevice
from python.signal_bot.models import Role, TrustLevel
if TYPE_CHECKING:

View File

@@ -21,10 +21,18 @@ class LLMClient:
temperature: Sampling temperature.
"""
def __init__(self, model: str, host: str, port: int = 11434, *, temperature: float = 0.1) -> None:
def __init__(
self,
*,
model: str,
host: str,
port: int = 11434,
temperature: float = 0.1,
timeout: int = 300,
) -> None:
self.model = model
self.temperature = temperature
self._client = httpx.Client(base_url=f"http://{host}:{port}", timeout=120)
self._client = httpx.Client(base_url=f"http://{host}:{port}", timeout=timeout)
def chat(self, prompt: str, image_data: bytes | None = None, system: str | None = None) -> str:
"""Send a text prompt and return the response."""

View File

@@ -11,12 +11,14 @@ if TYPE_CHECKING:
from collections.abc import Callable
import typer
from alembic.command import upgrade
from sqlalchemy.orm import Session
from tenacity import before_sleep_log, retry, stop_after_attempt, wait_exponential
from python.common import configure_logger, utcnow
from python.database_cli import DATABASES
from python.orm.common import get_postgres_engine
from python.orm.richie.dead_letter_message import DeadLetterMessage
from python.orm.signal_bot.models import DeadLetterMessage
from python.signal_bot.commands.inventory import handle_inventory_update
from python.signal_bot.commands.location import handle_location_request
from python.signal_bot.device_registry import DeviceRegistry, sync_roles
@@ -181,7 +183,7 @@ class Bot:
def main(
log_level: Annotated[str, typer.Option()] = "INFO",
log_level: Annotated[str, typer.Option()] = "DEBUG",
llm_timeout: Annotated[int, typer.Option()] = 600,
) -> None:
"""Run the Signal command and control bot."""
@@ -200,6 +202,8 @@ def main(
error = "INVENTORY_API_URL environment variable not set"
raise ValueError(error)
signal_bot_config = DATABASES["signal_bot"].alembic_config()
upgrade(signal_bot_config, "head")
engine = get_postgres_engine(name="SIGNALBOT")
sync_roles(engine)
config = BotConfig(