Skip to main content
Glama
models.py9.09 kB
""" IRIS Database Models SQLAlchemy models for core functionality """ from datetime import datetime from typing import Optional, Dict, Any from sqlalchemy import Column, Integer, String, DateTime, Text, Boolean, JSON, ForeignKey, BigInteger from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy.sql import func Base = declarative_base() class User(Base): """Telegram user model""" __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) telegram_id = Column(BigInteger, unique=True, index=True, nullable=False) username = Column(String(255), nullable=True) first_name = Column(String(255), nullable=True) last_name = Column(String(255), nullable=True) language_code = Column(String(10), default="en") # User preferences and settings preferences = Column(JSON, default=dict) is_active = Column(Boolean, default=True) is_premium = Column(Boolean, default=False) # Timestamps created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) last_activity = Column(DateTime(timezone=True), server_default=func.now()) # Relationships sessions = relationship("Session", back_populates="user", cascade="all, delete-orphan") files = relationship("File", back_populates="user", cascade="all, delete-orphan") def __repr__(self): return f"<User(telegram_id={self.telegram_id}, username={self.username})>" class Session(Base): """User conversation sessions with LLM""" __tablename__ = "sessions" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) session_id = Column(String(255), unique=True, index=True, nullable=False) # Session context and state context = Column(JSON, default=dict) # LLM conversation context state = Column(String(50), default="active") # active, paused, completed # Session metadata title = Column(String(500), nullable=True) summary = Column(Text, nullable=True) message_count = Column(Integer, default=0) # Timestamps created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) last_message_at = Column(DateTime(timezone=True), server_default=func.now()) # Relationships user = relationship("User", back_populates="sessions") messages = relationship("Message", back_populates="session", cascade="all, delete-orphan") def __repr__(self): return f"<Session(id={self.session_id}, user_id={self.user_id}, state={self.state})>" class ThreadCredentials(Base): """Thread-scoped credentials that survive agent memory limits""" __tablename__ = "thread_credentials" id = Column(Integer, primary_key=True, index=True) thread_id = Column(String(500), nullable=False, index=True) credential_type = Column(String(50), nullable=False) # 'pec', 'microsoft' # PEC credentials pec_email = Column(String(255), nullable=True) pec_password = Column(Text, nullable=True) # TODO: Encrypt in production # Microsoft credentials user_email = Column(String(255), nullable=True) # Metadata created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) last_used_at = Column(DateTime(timezone=True), server_default=func.now()) expires_at = Column(DateTime(timezone=True), nullable=True) def __repr__(self): return f"<ThreadCredentials(thread_id={self.thread_id}, type={self.credential_type})>" class Message(Base): """Individual messages in a session""" __tablename__ = "messages" id = Column(Integer, primary_key=True, index=True) session_id = Column(Integer, ForeignKey("sessions.id"), nullable=False) # Message content role = Column(String(20), nullable=False) # user, assistant, system content = Column(Text, nullable=False) message_type = Column(String(50), default="text") # text, file, command, etc. # Message metadata telegram_message_id = Column(BigInteger, nullable=True) tokens_used = Column(Integer, nullable=True) processing_time = Column(Integer, nullable=True) # milliseconds # Timestamps created_at = Column(DateTime(timezone=True), server_default=func.now()) # Relationships session = relationship("Session", back_populates="messages") def __repr__(self): return f"<Message(role={self.role}, type={self.message_type})>" class File(Base): """Uploaded files and documents""" __tablename__ = "files" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) # File identification file_id = Column(String(255), unique=True, index=True, nullable=False) telegram_file_id = Column(String(255), nullable=True) # File metadata filename = Column(String(500), nullable=False) original_filename = Column(String(500), nullable=True) file_type = Column(String(100), nullable=False) # pdf, docx, txt, etc. mime_type = Column(String(200), nullable=True) file_size = Column(BigInteger, nullable=True) # bytes # File storage file_path = Column(String(1000), nullable=True) # local storage path storage_type = Column(String(50), default="local") # local, s3, etc. # File analysis analysis_status = Column(String(50), default="pending") # pending, processing, completed, failed analysis_result = Column(JSON, default=dict) # LLM analysis results extracted_text = Column(Text, nullable=True) # File metadata description = Column(Text, nullable=True) tags = Column(JSON, default=list) # user-defined tags # Timestamps created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) analyzed_at = Column(DateTime(timezone=True), nullable=True) # Relationships user = relationship("User", back_populates="files") def __repr__(self): return f"<File(filename={self.filename}, type={self.file_type}, status={self.analysis_status})>" class SystemLog(Base): """System logs and events""" __tablename__ = "system_logs" id = Column(Integer, primary_key=True, index=True) # Log details level = Column(String(20), nullable=False) # DEBUG, INFO, WARNING, ERROR, CRITICAL message = Column(Text, nullable=False) component = Column(String(100), nullable=True) # telegram_bot, llm_core, etc. # Context user_id = Column(Integer, ForeignKey("users.id"), nullable=True) session_id = Column(String(255), nullable=True) log_metadata = Column(JSON, default=dict) # Timestamp created_at = Column(DateTime(timezone=True), server_default=func.now()) def __repr__(self): return f"<SystemLog(level={self.level}, component={self.component})>" class HybridBookingSession(Base): """Hybrid booking sessions for external meeting confirmations""" __tablename__ = "hybrid_booking_sessions" id = Column(Integer, primary_key=True, index=True) # Session identification session_id = Column(String(255), unique=True, index=True, nullable=False) booking_url = Column(String(500), nullable=False) # Organizer information organizer_email = Column(String(255), nullable=False) organizer_name = Column(String(255), nullable=False) # External attendee information external_email = Column(String(255), nullable=False) external_name = Column(String(255), nullable=False) # Meeting details meeting_subject = Column(String(500), nullable=False) meeting_duration = Column(Integer, nullable=False) # minutes # Internal attendees (JSON array of {email, name}) internal_attendees = Column(JSON, default=list) # Proposed time slots (JSON array of {start, end}) proposed_slots = Column(JSON, nullable=False) # Attachments (JSON array of {name, contentType, size, contentBytes}) attachments = Column(JSON, default=list) # Booking status and result status = Column(String(50), default="pending") # pending, confirmed, expired, cancelled confirmed_slot = Column(JSON, nullable=True) # {start, end} event_id = Column(String(255), nullable=True) # Microsoft Graph event ID # Timestamps created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) confirmed_at = Column(DateTime(timezone=True), nullable=True) expires_at = Column(DateTime(timezone=True), nullable=True) def __repr__(self): return f"<HybridBookingSession(session_id={self.session_id}, status={self.status})>"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ilvolodel/iris-legacy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server