Tribh/devops-copilot
0
1"""2persistence.py — Async SQLite session state (non-blocking)3"""4import aiosqlite5import json6from typing import Dict, Any, Optional, List7from devops_copilot.utils.logger import logger8 9 10class PersistenceLayer:11 """Async session state store backed by SQLite via aiosqlite."""12 13 def __init__(self, db_path: str = "agentnexus_state.db"):14 self.db_path = db_path15 16 async def setup(self):17 async with aiosqlite.connect(self.db_path) as db:18 await db.execute("""19 CREATE TABLE IF NOT EXISTS sessions (20 session_id TEXT PRIMARY KEY,21 state_json TEXT,22 updated_at REAL DEFAULT (strftime('%s', 'now'))23 )24 """)25 await db.commit()26 logger.info(f"[AsyncPersistence] Initialized at {self.db_path}")27 28 async def save_session(self, session_id: str, state: Dict[str, Any]):29 async with aiosqlite.connect(self.db_path) as db:30 await db.execute(31 "INSERT OR REPLACE INTO sessions (session_id, state_json) VALUES (?,?)",32 (session_id, json.dumps(state))33 )34 await db.commit()35 logger.debug(f"Saved session {session_id}")36 37 async def load_session(self, session_id: str) -> Optional[Dict[str, Any]]:38 async with aiosqlite.connect(self.db_path) as db:39 async with db.execute(40 "SELECT state_json FROM sessions WHERE session_id=?", (session_id,)41 ) as cur:42 row = await cur.fetchone()43 return json.loads(row[0]) if row else None44 45 async def list_sessions(self) -> List[str]:46 async with aiosqlite.connect(self.db_path) as db:47 async with db.execute("SELECT session_id FROM sessions") as cur:48 rows = await cur.fetchall()49 return [r[0] for r in rows]50 51 async def set_approved(self, session_id: str):52 """Set human_approved=True in session metadata. Called by the API."""53 state = await self.load_session(session_id)54 if state is None:55 raise KeyError(f"Session '{session_id}' not found.")56 state.setdefault("metadata", {})["human_approved"] = True57 await self.save_session(session_id, state)58 logger.info(f"✅ Approval granted for session {session_id}")59 