Spaces:
Runtime error
Runtime error
| """ | |
| Session Store - Persistent storage for conversation memory | |
| Saves and loads user sessions across app restarts | |
| """ | |
| import json | |
| import os | |
| from datetime import datetime | |
| from pathlib import Path | |
| from typing import Optional, Dict, Any | |
| class SessionStore: | |
| """Manages persistent storage of conversation sessions""" | |
| def __init__(self, storage_dir: str = "sessions"): | |
| self.storage_dir = Path(storage_dir) | |
| self.storage_dir.mkdir(parents=True, exist_ok=True) | |
| def save_session(self, user_id: str, session_data: Dict[str, Any]) -> None: | |
| """ | |
| Save user session to disk | |
| Args: | |
| user_id: Unique user identifier | |
| session_data: Session data to save (memory state) | |
| """ | |
| session_file = self.storage_dir / f"{user_id}.json" | |
| # Add metadata | |
| session_data['last_updated'] = datetime.now().isoformat() | |
| session_data['user_id'] = user_id | |
| with open(session_file, 'w', encoding='utf-8') as f: | |
| json.dump(session_data, f, ensure_ascii=False, indent=2) | |
| def load_session(self, user_id: str) -> Optional[Dict[str, Any]]: | |
| """ | |
| Load user session from disk | |
| Args: | |
| user_id: Unique user identifier | |
| Returns: | |
| Session data or None if not found | |
| """ | |
| session_file = self.storage_dir / f"{user_id}.json" | |
| if not session_file.exists(): | |
| return None | |
| try: | |
| with open(session_file, 'r', encoding='utf-8') as f: | |
| return json.load(f) | |
| except (json.JSONDecodeError, IOError) as e: | |
| print(f"⚠️ Error loading session for {user_id}: {e}") | |
| return None | |
| def delete_session(self, user_id: str) -> bool: | |
| """ | |
| Delete user session | |
| Args: | |
| user_id: Unique user identifier | |
| Returns: | |
| True if deleted, False if not found | |
| """ | |
| session_file = self.storage_dir / f"{user_id}.json" | |
| if session_file.exists(): | |
| session_file.unlink() | |
| return True | |
| return False | |
| def list_sessions(self) -> list: | |
| """ | |
| List all stored sessions | |
| Returns: | |
| List of user IDs with sessions | |
| """ | |
| return [f.stem for f in self.storage_dir.glob("*.json")] | |
| def get_session_info(self, user_id: str) -> Optional[Dict[str, Any]]: | |
| """ | |
| Get session metadata without loading full data | |
| Args: | |
| user_id: Unique user identifier | |
| Returns: | |
| Session metadata or None | |
| """ | |
| session_file = self.storage_dir / f"{user_id}.json" | |
| if not session_file.exists(): | |
| return None | |
| try: | |
| with open(session_file, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| return { | |
| 'user_id': data.get('user_id'), | |
| 'last_updated': data.get('last_updated'), | |
| 'has_profile': bool(data.get('user_profile')), | |
| 'current_agent': data.get('current_agent'), | |
| 'conversation_count': len(data.get('conversation_history', [])) | |
| } | |
| except (json.JSONDecodeError, IOError): | |
| return None | |
| def cleanup_old_sessions(self, days: int = 30) -> int: | |
| """ | |
| Delete sessions older than specified days | |
| Args: | |
| days: Number of days to keep sessions | |
| Returns: | |
| Number of sessions deleted | |
| """ | |
| from datetime import timedelta | |
| cutoff_date = datetime.now() - timedelta(days=days) | |
| deleted_count = 0 | |
| for session_file in self.storage_dir.glob("*.json"): | |
| try: | |
| with open(session_file, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| last_updated = datetime.fromisoformat(data.get('last_updated', '')) | |
| if last_updated < cutoff_date: | |
| session_file.unlink() | |
| deleted_count += 1 | |
| except (json.JSONDecodeError, IOError, ValueError): | |
| continue | |
| return deleted_count | |
| # Global instance | |
| _session_store = None | |
| def get_session_store() -> SessionStore: | |
| """Get global session store instance""" | |
| global _session_store | |
| if _session_store is None: | |
| _session_store = SessionStore() | |
| return _session_store | |