| | """ |
| | Message model representing a single message in a conversation. |
| | |
| | Per @specs/001-chatbot-mcp/data-model.md |
| | """ |
| | from sqlmodel import SQLModel, Field, Relationship, Column |
| | from typing import TYPE_CHECKING, Optional, Any, Dict |
| | from datetime import datetime |
| | from uuid import UUID, uuid4 |
| | from enum import Enum |
| | from sqlalchemy import JSON |
| |
|
| | if TYPE_CHECKING: |
| | from models.conversation import ConversationTable |
| |
|
| |
|
| | class MessageRole(str, Enum): |
| | """Message sender role.""" |
| | USER = "user" |
| | ASSISTANT = "assistant" |
| |
|
| |
|
| | class MessageTable(SQLModel, table=True): |
| | """ |
| | A single message in a conversation. |
| | |
| | Messages are owned by a user through their conversation. All queries MUST |
| | filter by user_id (via conversation) to ensure data isolation. |
| | """ |
| | __tablename__ = "messages" |
| |
|
| | |
| | id: UUID = Field( |
| | default_factory=uuid4, |
| | primary_key=True, |
| | index=True, |
| | description="Unique message identifier" |
| | ) |
| |
|
| | |
| | conversation_id: UUID = Field( |
| | foreign_key="conversations.id", |
| | index=True, |
| | nullable=False, |
| | description="ID of the conversation this message belongs to" |
| | ) |
| |
|
| | |
| | role: MessageRole = Field( |
| | nullable=False, |
| | description="Message sender: 'user' or 'assistant'" |
| | ) |
| |
|
| | content: str = Field( |
| | nullable=False, |
| | max_length=5000, |
| | description="Message content (plaintext)" |
| | ) |
| |
|
| | |
| | created_at: datetime = Field( |
| | default_factory=datetime.utcnow, |
| | nullable=False, |
| | index=True, |
| | description="Timestamp when message was created" |
| | ) |
| |
|
| | |
| | |
| | tool_metadata: Optional[Dict[str, Any]] = Field( |
| | default=None, |
| | sa_column=Column(JSON), |
| | description="Tool calls, tokens used, error information" |
| | ) |
| |
|
| | |
| | conversation: "ConversationTable" = Relationship(back_populates="messages") |
| |
|