"""Database abstraction layer with SQLite and Postgres implementations.The module exposes a `Database` factory function that returns an instance of`SQLiteDatabase` or `PostgresDatabase` depending on the provided connectionstring. Supported schemes are:: sqlite://<path | :memory:> postgresql://<user>:<pass>@<host>:<port>/<dbname> postgres://<user>:<pass>@<host>:<port>/<dbname>All implementations share the same async API."""from__future__importannotationsimportabcfromtypingimportAny,List,Literalfromagentstr.modelsimportMessage,Userfromagentstr.loggerimportget_loggerlogger=get_logger(__name__)
[docs]classBaseDatabase(abc.ABC):"""Abstract base class for concrete database backends."""
[docs]def__init__(self,conn_str:str,agent_name:str|None=None):self.conn_str=conn_strself.agent_name=agent_nameself.conn=None# Will be set by :py:meth:`async_init`.
[docs]@abc.abstractmethodasyncdefasync_init(self)->"BaseDatabase":"""Perform any asynchronous initialisation required for the backend."""
[docs]@abc.abstractmethodasyncdefclose(self)->None:"""Close the underlying connection (if any)."""
# ------------------------------------------------------------------# CRUD operations (synchronous wrappers around async where sensible)# ------------------------------------------------------------------
[docs]@abc.abstractmethodasyncdefget_user(self,user_id:str)->"User":"""Fetch a :class:`User` by *user_id*. Non-existent users yield a default model with a zero balance."""
[docs]@abc.abstractmethodasyncdefupsert_user(self,user:"User")->None:"""Create or update *user* in storage atomically."""
# ------------------------------------------------------------------# Message history operations# ------------------------------------------------------------------
[docs]@abc.abstractmethodasyncdefadd_message(self,thread_id:str,user_id:str,role:Literal["user","agent","tool"],message:str="",content:str="",kind:str="request",satoshis:int|None=None,extra_inputs:dict[str,Any]={},extra_outputs:dict[str,Any]={},)->"Message":"""Append a message to a thread and return the stored model."""
[docs]@abc.abstractmethodasyncdefget_messages(self,thread_id:str,user_id:str,*,limit:int|None=None,before_idx:int|None=None,after_idx:int|None=None,reverse:bool=False,)->List["Message"]:"""Retrieve messages for *thread_id* ordered by idx."""
# ------------------------------------------------------------------# Current thread ID helpers# ------------------------------------------------------------------
[docs]@abc.abstractmethodasyncdefget_current_thread_id(self,user_id:str)->str|None:"""Return the current thread id for *user_id* within this agent scope."""
[docs]@abc.abstractmethodasyncdefset_current_thread_id(self,user_id:str,thread_id:str|None)->None:"""Persist *thread_id* as the current thread for *user_id*."""