Merge pull request #26 from manmohan659/fix/missing-models

fix: add missing SQLAlchemy models to auth and chat-api
This commit is contained in:
Manmohan 2026-04-16 16:50:22 -04:00 committed by GitHub
commit b5fbebb63f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 195 additions and 1 deletions

2
.gitignore vendored
View File

@ -4,7 +4,7 @@ __pycache__/
dev-ignore/
report.md
eval_bundle/
models/
/models/
.terraform/
*.tfstate
*.tfstate.*

View File

@ -0,0 +1,3 @@
from .user import User
__all__ = ["User"]

View File

@ -0,0 +1,61 @@
"""SQLAlchemy 2.0 async model for the `users` table."""
from __future__ import annotations
import uuid
from datetime import datetime, timezone
import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column
from ..database import Base
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
class User(Base):
__tablename__ = "users"
__table_args__ = (
sa.UniqueConstraint("provider", "provider_id", name="uq_users_provider_identity"),
)
id: Mapped[uuid.UUID] = mapped_column(
sa.Uuid(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
email: Mapped[str] = mapped_column(sa.String(255), unique=True, nullable=False)
name: Mapped[str | None] = mapped_column(sa.String(255), nullable=True)
avatar_url: Mapped[str | None] = mapped_column(sa.Text(), nullable=True)
provider: Mapped[str] = mapped_column(sa.String(50), nullable=False)
provider_id: Mapped[str] = mapped_column(sa.String(255), nullable=False)
created_at: Mapped[datetime] = mapped_column(
sa.DateTime(timezone=True),
default=_utcnow,
nullable=False,
)
updated_at: Mapped[datetime] = mapped_column(
sa.DateTime(timezone=True),
default=_utcnow,
onupdate=_utcnow,
nullable=False,
)
last_login_at: Mapped[datetime] = mapped_column(
sa.DateTime(timezone=True),
default=_utcnow,
nullable=False,
)
def to_dict(self) -> dict:
return {
"id": str(self.id),
"email": self.email,
"name": self.name,
"avatar_url": self.avatar_url,
"provider": self.provider,
"provider_id": self.provider_id,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
"last_login_at": self.last_login_at.isoformat() if self.last_login_at else None,
}

View File

@ -0,0 +1,4 @@
from .conversation import Conversation
from .message import Message
__all__ = ["Conversation", "Message"]

View File

@ -0,0 +1,60 @@
"""SQLAlchemy 2.0 async model for the `conversations` table."""
from __future__ import annotations
import uuid
from datetime import datetime, timezone
import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..database import Base
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
class Conversation(Base):
__tablename__ = "conversations"
id: Mapped[uuid.UUID] = mapped_column(
sa.Uuid(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
user_id: Mapped[uuid.UUID] = mapped_column(
sa.Uuid(as_uuid=True),
sa.ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
title: Mapped[str] = mapped_column(sa.String(500), nullable=False, default="New conversation")
model_tag: Mapped[str] = mapped_column(sa.String(100), nullable=False, default="default")
created_at: Mapped[datetime] = mapped_column(
sa.DateTime(timezone=True),
default=_utcnow,
nullable=False,
)
updated_at: Mapped[datetime] = mapped_column(
sa.DateTime(timezone=True),
default=_utcnow,
onupdate=_utcnow,
nullable=False,
)
messages: Mapped[list["Message"]] = relationship( # noqa: F821
"Message",
back_populates="conversation",
cascade="all, delete-orphan",
order_by="Message.created_at",
)
def to_dict(self) -> dict:
return {
"id": str(self.id),
"user_id": str(self.user_id),
"title": self.title,
"model_tag": self.model_tag,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
}

View File

@ -0,0 +1,66 @@
"""SQLAlchemy 2.0 async model for the `messages` table."""
from __future__ import annotations
import uuid
from datetime import datetime, timezone
import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..database import Base
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
MESSAGE_ROLES = ("user", "assistant", "system")
class Message(Base):
__tablename__ = "messages"
__table_args__ = (
sa.CheckConstraint(
"role IN ('user', 'assistant', 'system')",
name="ck_messages_role",
),
sa.Index("ix_messages_conversation_created", "conversation_id", "created_at"),
)
id: Mapped[uuid.UUID] = mapped_column(
sa.Uuid(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
conversation_id: Mapped[uuid.UUID] = mapped_column(
sa.Uuid(as_uuid=True),
sa.ForeignKey("conversations.id", ondelete="CASCADE"),
nullable=False,
)
role: Mapped[str] = mapped_column(sa.String(20), nullable=False)
content: Mapped[str] = mapped_column(sa.Text(), nullable=False)
token_count: Mapped[int | None] = mapped_column(sa.Integer(), nullable=True)
model_tag: Mapped[str | None] = mapped_column(sa.String(100), nullable=True)
inference_time_ms: Mapped[int | None] = mapped_column(sa.Integer(), nullable=True)
created_at: Mapped[datetime] = mapped_column(
sa.DateTime(timezone=True),
default=_utcnow,
nullable=False,
)
conversation: Mapped["Conversation"] = relationship( # noqa: F821
"Conversation",
back_populates="messages",
)
def to_dict(self) -> dict:
return {
"id": str(self.id),
"conversation_id": str(self.conversation_id),
"role": self.role,
"content": self.content,
"token_count": self.token_count or 0,
"model_tag": self.model_tag or "",
"inference_time_ms": self.inference_time_ms or 0,
"created_at": self.created_at.isoformat() if self.created_at else None,
}