""" app/services/status_service.py Tracks server startup time and agent activity. """ from __future__ import annotations import logging import sqlite3 from datetime import datetime, timezone from typing import Optional from app.config import AGENT_STALE_AFTER_SECONDS from app.database import get_conn, get_write_conn logger = logging.getLogger(__name__) _server_started_at: datetime = datetime.now(timezone.utc) def server_started_at() -> datetime: return _server_started_at def _now_iso() -> str: return datetime.now(timezone.utc).isoformat() # --------------------------------------------------------------------------- # Agent activity # --------------------------------------------------------------------------- def record_agent_activity(agent_id: str, result_type: str) -> None: """Upsert agent activity record on every tool call.""" now = _now_iso() with get_write_conn() as conn: conn.execute( """ INSERT INTO agent_activity (agent_id, last_seen_at, last_fetch_at, last_result_type) VALUES (?, ?, ?, ?) ON CONFLICT(agent_id) DO UPDATE SET last_seen_at = excluded.last_seen_at, last_fetch_at = excluded.last_fetch_at, last_result_type = excluded.last_result_type """, (agent_id, now, now, result_type), ) logger.debug("Agent activity recorded agent=%s result=%s", agent_id, result_type) def get_latest_agent_activity() -> Optional[sqlite3.Row]: """Return the most recently active agent row, or None.""" with get_conn() as conn: return conn.execute( "SELECT * FROM agent_activity ORDER BY last_seen_at DESC LIMIT 1" ).fetchone() def is_agent_connected() -> bool: """True if the most recent agent activity is within the stale threshold.""" row = get_latest_agent_activity() if row is None: return False last_seen = datetime.fromisoformat(row["last_seen_at"]) now = datetime.now(timezone.utc) if last_seen.tzinfo is None: last_seen = last_seen.replace(tzinfo=timezone.utc) delta = (now - last_seen).total_seconds() return delta <= AGENT_STALE_AFTER_SECONDS