scratch_chat / chat_agent /models /chat_session.py
WebashalarForML's picture
Upload 178 files
330b6e4 verified
"""ChatSession model for managing user chat sessions."""
from datetime import datetime, timedelta
from sqlalchemy import Column, String, DateTime, Integer, Boolean, JSON
from sqlalchemy.orm import relationship
from .base import BaseModel, db, GUID
class ChatSession(BaseModel):
"""Model for managing user chat sessions."""
__tablename__ = 'chat_sessions'
# Core session fields
user_id = Column(GUID(), nullable=False, index=True)
language = Column(String(50), nullable=False, default='python')
# Activity tracking
last_active = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
message_count = Column(Integer, default=0, nullable=False)
is_active = Column(Boolean, default=True, nullable=False, index=True)
# Session metadata
session_metadata = Column(JSON, default=dict) # Additional session context, preferences, etc.
# Relationships
messages = relationship("Message", back_populates="session", cascade="all, delete-orphan")
language_context = relationship("LanguageContext", back_populates="session", uselist=False, cascade="all, delete-orphan")
def __init__(self, user_id, language='python', session_metadata=None):
"""Initialize a new chat session."""
super().__init__()
self.user_id = user_id
self.language = language
self.last_active = datetime.utcnow()
self.message_count = 0
self.is_active = True
self.session_metadata = session_metadata or {}
def update_activity(self):
"""Update the last active timestamp."""
self.last_active = datetime.utcnow()
db.session.commit()
def increment_message_count(self):
"""Increment the message count for this session."""
self.message_count += 1
self.update_activity()
def set_language(self, language):
"""Set the programming language for this session."""
self.language = language
self.update_activity()
def deactivate(self):
"""Mark the session as inactive."""
self.is_active = False
db.session.commit()
def is_expired(self, timeout_seconds=3600):
"""Check if the session has expired based on last activity."""
if not self.last_active:
return True
expiry_time = self.last_active + timedelta(seconds=timeout_seconds)
return datetime.utcnow() > expiry_time
def get_recent_messages(self, limit=10):
"""Get recent messages for this session."""
# Import here to avoid circular imports
from .message import Message
return (db.session.query(Message)
.filter(Message.session_id == self.id)
.order_by(Message.timestamp.desc())
.limit(limit)
.all())
def to_dict(self):
"""Convert session to dictionary with formatted timestamps."""
data = super().to_dict()
# Format timestamps as ISO strings for JSON serialization
if self.last_active:
data['last_active'] = self.last_active.isoformat()
return data
@classmethod
def create_session(cls, user_id, language='python', session_metadata=None):
"""Create a new chat session."""
session = cls(user_id=user_id, language=language, session_metadata=session_metadata)
db.session.add(session)
db.session.commit()
return session
@classmethod
def get_active_sessions(cls, user_id=None):
"""Get all active sessions, optionally filtered by user."""
query = db.session.query(cls).filter(cls.is_active == True)
if user_id:
query = query.filter(cls.user_id == user_id)
return query.all()
@classmethod
def cleanup_expired_sessions(cls, timeout_seconds=3600):
"""Clean up expired sessions."""
cutoff_time = datetime.utcnow() - timedelta(seconds=timeout_seconds)
expired_sessions = (db.session.query(cls)
.filter(cls.last_active < cutoff_time)
.filter(cls.is_active == True)
.all())
for session in expired_sessions:
session.deactivate()
return len(expired_sessions)
def __repr__(self):
"""String representation of the session."""
return f"<ChatSession(id={self.id}, user_id={self.user_id}, language={self.language}, active={self.is_active})>"