""" backend/memory/supabase_backend.py — Supabase implementation of MemoryBackend. """ from typing import Any, Dict, List, Optional from .memory_backend import MemoryBackend class SupabaseMemoryBackend(MemoryBackend): """ Wrappa il client Supabase esistente in api.state per l'uso nel MemorySynchronizer. Il client viene risolto late-binding al momento di ogni operazione (non all'import) per supportare configurazioni in cui Supabase si connette dopo l'import del modulo. """ def __init__(self): self.is_connected = self._client() is not None def _client(self): """Risolve il client Supabase corrente — None se non configurato.""" try: from api.state import _sb return _sb except Exception: return None def _require_client(self): """Lancia RuntimeError se il client non è disponibile.""" c = self._client() if c is None: raise RuntimeError( "Supabase client non disponibile: imposta SUPABASE_URL e SUPABASE_KEY " "nelle variabili HF Space/env prima di usare SupabaseMemoryBackend." ) return c async def connect(self, config: Dict[str, Any]) -> None: """Il client è già connesso via api.state.""" self.is_connected = self._client() is not None async def disconnect(self) -> None: """Nessuna operazione di chiusura necessaria per il client HTTP stateless.""" self.is_connected = False async def add_memory(self, user_id: str, memory_data: Dict[str, Any], memory_id: Optional[str] = None) -> str: c = self._require_client() data = {**memory_data, "user_id": user_id} if memory_id: data["id"] = memory_id result = c.table("memories").insert(data).execute() return result.data[0]["id"] async def get_memory(self, user_id: str, memory_id: str) -> Optional[Dict[str, Any]]: c = self._require_client() result = c.table("memories").select("*").eq("user_id", user_id).eq("id", memory_id).execute() return result.data[0] if result.data else None async def list_memories(self, user_id: str, limit: int = 100, offset: int = 0) -> List[Dict[str, Any]]: c = self._require_client() result = c.table("memories").select("*").eq("user_id", user_id).range(offset, offset + limit).execute() return result.data async def update_memory(self, user_id: str, memory_id: str, new_data: Dict[str, Any]) -> bool: c = self._require_client() result = c.table("memories").update(new_data).eq("user_id", user_id).eq("id", memory_id).execute() return len(result.data) > 0 async def delete_memory(self, user_id: str, memory_id: str) -> bool: c = self._require_client() result = c.table("memories").delete().eq("user_id", user_id).eq("id", memory_id).execute() return len(result.data) > 0