Spaces:
Sleeping
Sleeping
Peter Michael Gits
feat: Add Streamlit-native WebRTC speech-to-text using unmute.sh patterns
21fac9b | """ | |
| Session Manager for ChatCal Voice - Handles user sessions in Gradio environment. | |
| Since we're on Hugging Face without persistent storage, we'll use in-memory | |
| session management with automatic cleanup. | |
| """ | |
| import time | |
| import uuid | |
| from typing import Dict, List, Any, Optional | |
| from datetime import datetime, timedelta | |
| from .session import SessionData | |
| from .config import config | |
| class SessionManager: | |
| """Manages user sessions for the voice-enabled ChatCal.""" | |
| def __init__(self): | |
| self.sessions: Dict[str, SessionData] = {} | |
| self.last_cleanup = time.time() | |
| self.cleanup_interval = 300 # 5 minutes | |
| async def get_session(self, session_id: Optional[str] = None) -> SessionData: | |
| """Get or create a session.""" | |
| # Auto-cleanup old sessions periodically | |
| await self._cleanup_expired_sessions() | |
| # Create new session if none provided | |
| if not session_id: | |
| session_id = self._generate_session_id() | |
| # Return existing session or create new one | |
| if session_id in self.sessions: | |
| session = self.sessions[session_id] | |
| session.last_activity = datetime.now() | |
| return session | |
| # Create new session | |
| session = SessionData(session_id=session_id) | |
| self.sessions[session_id] = session | |
| return session | |
| def _generate_session_id(self) -> str: | |
| """Generate a unique session ID.""" | |
| timestamp = int(time.time()) | |
| unique_id = str(uuid.uuid4())[:8] | |
| return f"chatcal_{timestamp}_{unique_id}" | |
| async def _cleanup_expired_sessions(self): | |
| """Clean up expired sessions.""" | |
| current_time = time.time() | |
| # Only run cleanup periodically | |
| if current_time - self.last_cleanup < self.cleanup_interval: | |
| return | |
| cutoff_time = datetime.now() - timedelta(minutes=config.session_timeout_minutes) | |
| expired_sessions = [ | |
| session_id for session_id, session in self.sessions.items() | |
| if session.last_activity < cutoff_time | |
| ] | |
| for session_id in expired_sessions: | |
| del self.sessions[session_id] | |
| if expired_sessions: | |
| print(f"🧹 Cleaned up {len(expired_sessions)} expired sessions") | |
| self.last_cleanup = current_time | |
| async def delete_session(self, session_id: str): | |
| """Delete a specific session.""" | |
| if session_id in self.sessions: | |
| del self.sessions[session_id] | |
| def get_session_count(self) -> int: | |
| """Get the number of active sessions.""" | |
| return len(self.sessions) | |
| def get_session_stats(self) -> Dict[str, Any]: | |
| """Get session statistics.""" | |
| return { | |
| "active_sessions": len(self.sessions), | |
| "total_messages": sum(len(s.conversation_history) for s in self.sessions.values()), | |
| "sessions_with_user_info": sum( | |
| 1 for s in self.sessions.values() | |
| if s.user_info.get("name") or s.user_info.get("email") | |
| ) | |
| } | |
| # Global session manager instance | |
| session_manager = SessionManager() |