| """ |
| Session Data Model for ChatCal Voice. |
| |
| Handles conversation state, user information, and session persistence |
| in the Hugging Face Gradio environment. |
| """ |
|
|
| from typing import Dict, List, Any, Optional |
| from datetime import datetime |
| from dataclasses import dataclass, field |
|
|
|
|
| @dataclass |
| class SessionData: |
| """Data structure for user sessions.""" |
| |
| session_id: str |
| created_at: datetime = field(default_factory=datetime.now) |
| last_activity: datetime = field(default_factory=datetime.now) |
| |
| |
| user_info: Dict[str, Any] = field(default_factory=lambda: { |
| "name": None, |
| "email": None, |
| "phone": None, |
| "preferences": {}, |
| "timezone": None |
| }) |
| |
| |
| conversation_history: List[Dict[str, str]] = field(default_factory=list) |
| |
| |
| session_state: Dict[str, Any] = field(default_factory=lambda: { |
| "pending_operation": None, |
| "operation_context": {}, |
| "awaiting_clarification": False, |
| "last_voice_input": None, |
| "voice_enabled": True |
| }) |
| |
| |
| booking_history: List[Dict[str, Any]] = field(default_factory=list) |
| |
| def add_message(self, role: str, content: str): |
| """Add a message to conversation history.""" |
| self.conversation_history.append({ |
| "role": role, |
| "content": content, |
| "timestamp": datetime.now().isoformat() |
| }) |
| |
| |
| max_history = 50 |
| if len(self.conversation_history) > max_history: |
| self.conversation_history = self.conversation_history[-max_history:] |
| |
| self.last_activity = datetime.now() |
| |
| def get_recent_messages(self, count: int = 10) -> List[Dict[str, str]]: |
| """Get recent conversation messages.""" |
| return self.conversation_history[-count:] if self.conversation_history else [] |
| |
| def update_user_info(self, **kwargs): |
| """Update user information.""" |
| for key, value in kwargs.items(): |
| if key in self.user_info and value: |
| self.user_info[key] = value |
| self.last_activity = datetime.now() |
| |
| def has_required_user_info(self) -> bool: |
| """Check if session has minimum required user information.""" |
| return ( |
| bool(self.user_info.get("name")) and |
| (bool(self.user_info.get("email")) or bool(self.user_info.get("phone"))) |
| ) |
| |
| def get_user_summary(self) -> str: |
| """Get a summary of user information.""" |
| name = self.user_info.get("name", "Unknown") |
| contact = self.user_info.get("email") or self.user_info.get("phone") or "No contact" |
| return f"{name} ({contact})" |
| |
| def set_pending_operation(self, operation: str, context: Dict[str, Any] = None): |
| """Set a pending operation with context.""" |
| self.session_state["pending_operation"] = operation |
| self.session_state["operation_context"] = context or {} |
| self.session_state["awaiting_clarification"] = False |
| self.last_activity = datetime.now() |
| |
| def clear_pending_operation(self): |
| """Clear any pending operation.""" |
| self.session_state["pending_operation"] = None |
| self.session_state["operation_context"] = {} |
| self.session_state["awaiting_clarification"] = False |
| self.last_activity = datetime.now() |
| |
| def add_booking(self, booking_info: Dict[str, Any]): |
| """Add a booking to the session history.""" |
| booking_info["session_id"] = self.session_id |
| booking_info["timestamp"] = datetime.now().isoformat() |
| self.booking_history.append(booking_info) |
| self.last_activity = datetime.now() |
| |
| def get_session_duration_minutes(self) -> int: |
| """Get session duration in minutes.""" |
| delta = datetime.now() - self.created_at |
| return int(delta.total_seconds() / 60) |
| |
| def is_expired(self, timeout_minutes: int = 30) -> bool: |
| """Check if session is expired.""" |
| delta = datetime.now() - self.last_activity |
| return delta.total_seconds() > (timeout_minutes * 60) |
| |
| def to_dict(self) -> Dict[str, Any]: |
| """Convert session to dictionary for serialization.""" |
| return { |
| "session_id": self.session_id, |
| "created_at": self.created_at.isoformat(), |
| "last_activity": self.last_activity.isoformat(), |
| "user_info": self.user_info, |
| "conversation_count": len(self.conversation_history), |
| "session_state": self.session_state, |
| "booking_count": len(self.booking_history) |
| } |
| |
| @classmethod |
| def from_dict(cls, data: Dict[str, Any]) -> 'SessionData': |
| """Create session from dictionary.""" |
| session = cls(session_id=data["session_id"]) |
| session.created_at = datetime.fromisoformat(data["created_at"]) |
| session.last_activity = datetime.fromisoformat(data["last_activity"]) |
| session.user_info = data.get("user_info", {}) |
| session.session_state = data.get("session_state", {}) |
| return session |