Spaces:
Build error
Build error
| """SQLAlchemy models for Project Memory.""" | |
| from sqlalchemy import Column, String, DateTime, ForeignKey, Text, Enum, JSON, Boolean | |
| from sqlalchemy.orm import relationship | |
| from datetime import datetime | |
| import uuid | |
| import enum | |
| import random | |
| from app.database import Base | |
| # Special user ID for AI Agent | |
| AI_AGENT_USER_ID = "ai-agent" | |
| def generate_uuid() -> str: | |
| """Generate a new UUID string.""" | |
| return str(uuid.uuid4()) | |
| def generate_user_id(first_name: str) -> str: | |
| """Generate user ID: first 3 letters of firstname + 4 random digits. | |
| Example: 'Amal' -> 'ama1234' | |
| """ | |
| prefix = first_name[:3].lower() | |
| suffix = ''.join([str(random.randint(0, 9)) for _ in range(4)]) | |
| return f"{prefix}{suffix}" | |
| class ActorType(str, enum.Enum): | |
| """Who performed the action.""" | |
| human = "human" | |
| agent = "agent" | |
| class ActionType(str, enum.Enum): | |
| """Type of action recorded.""" | |
| task_completed = "task_completed" | |
| doc_generated = "doc_generated" | |
| query_answered = "query_answered" | |
| class TaskStatus(str, enum.Enum): | |
| """Task status states.""" | |
| todo = "todo" | |
| in_progress = "in_progress" | |
| done = "done" | |
| class User(Base): | |
| """User account.""" | |
| __tablename__ = "users" | |
| id = Column(String, primary_key=True) # Generated as first_name[:3] + 4 random digits | |
| first_name = Column(String, nullable=False) | |
| last_name = Column(String, nullable=False) | |
| avatar_url = Column(String, nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| # Relationships | |
| memberships = relationship("ProjectMembership", back_populates="user") | |
| created_projects = relationship("Project", back_populates="creator") | |
| log_entries = relationship("LogEntry", back_populates="user") | |
| def name(self) -> str: | |
| """Full name for backward compatibility.""" | |
| return f"{self.first_name} {self.last_name}" | |
| class Project(Base): | |
| """Project that contains tasks and memory. | |
| Option A: project name is also the stable project ID. We persist the ID explicitly | |
| from the tools layer (create_project uses the provided name as id). | |
| """ | |
| __tablename__ = "projects" | |
| # ID is provided by callers (equal to the project name); no UUID default | |
| id = Column(String, primary_key=True) | |
| name = Column(String, nullable=False) | |
| description = Column(Text, nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| created_by = Column(String, ForeignKey("users.id"), nullable=True) | |
| agent_enabled = Column(Boolean, default=False) # Whether AI agent is enabled for this project | |
| # Relationships | |
| creator = relationship("User", back_populates="created_projects") | |
| memberships = relationship("ProjectMembership", back_populates="project") | |
| tasks = relationship("Task", back_populates="project") | |
| log_entries = relationship("LogEntry", back_populates="project") | |
| class ProjectMembership(Base): | |
| """Association between users and projects.""" | |
| __tablename__ = "project_memberships" | |
| id = Column(String, primary_key=True, default=generate_uuid) | |
| project_id = Column(String, ForeignKey("projects.id"), nullable=False) | |
| user_id = Column(String, ForeignKey("users.id"), nullable=False) | |
| role = Column(String, default="member") # "owner" or "member" | |
| joined_at = Column(DateTime, default=datetime.utcnow) | |
| # Relationships | |
| project = relationship("Project", back_populates="memberships") | |
| user = relationship("User", back_populates="memberships") | |
| class Task(Base): | |
| """Task within a project.""" | |
| __tablename__ = "tasks" | |
| id = Column(String, primary_key=True, default=generate_uuid) | |
| project_id = Column(String, ForeignKey("projects.id"), nullable=False) | |
| title = Column(String, nullable=False) | |
| description = Column(Text, nullable=True) | |
| status = Column(Enum(TaskStatus), default=TaskStatus.todo) | |
| assigned_to = Column(String, nullable=True) # userId or "agent" | |
| working_by = Column(String, nullable=True) # User ID currently working on this task | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| completed_at = Column(DateTime, nullable=True) | |
| # Relationships | |
| project = relationship("Project", back_populates="tasks") | |
| log_entries = relationship("LogEntry", back_populates="task") | |
| class LogEntry(Base): | |
| """ | |
| The core of project memory. | |
| Records what was done, by whom, and stores LLM-generated documentation. | |
| """ | |
| __tablename__ = "log_entries" | |
| id = Column(String, primary_key=True, default=generate_uuid) | |
| project_id = Column(String, ForeignKey("projects.id"), nullable=False) | |
| task_id = Column(String, ForeignKey("tasks.id"), nullable=True) | |
| user_id = Column(String, ForeignKey("users.id"), nullable=True) | |
| actor_type = Column(Enum(ActorType), nullable=False) | |
| action_type = Column(Enum(ActionType), nullable=False) | |
| raw_input = Column(Text, nullable=False) # What user typed | |
| code_snippet = Column(Text, nullable=True) # Optional code | |
| generated_doc = Column(Text, nullable=False) # LLM-generated documentation | |
| tags = Column(JSON, default=list) # Extracted tags | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| # Relationships | |
| project = relationship("Project", back_populates="log_entries") | |
| task = relationship("Task", back_populates="log_entries") | |
| user = relationship("User", back_populates="log_entries") | |