22from sqlmodel import Field , SmallInteger , Column , JSON , String
33from typing import Optional
44from enum import IntEnum
5+ from datetime import datetime
56from sqlalchemy_utils import ChoiceType
67from app .model .abstract .model import AbstractModel , DefaultTimes
78from pydantic import BaseModel , model_validator
@@ -13,6 +14,16 @@ class ChatStatus(IntEnum):
1314
1415
1516class ChatHistory (AbstractModel , DefaultTimes , table = True ):
17+ """
18+ Chat history model with timestamp tracking.
19+
20+ Inherits from DefaultTimes which provides:
21+ - created_at: timestamp when record is created (auto-populated)
22+ - updated_at: timestamp when record is last modified (auto-updated)
23+ - deleted_at: timestamp for soft deletion (nullable)
24+
25+ For legacy records without timestamps, sorting falls back to id ordering.
26+ """
1627 id : int = Field (default = None , primary_key = True )
1728 user_id : int = Field (index = True )
1829 task_id : str = Field (index = True , unique = True )
@@ -70,13 +81,22 @@ class ChatHistoryOut(BaseModel):
7081 summary : str | None = None
7182 tokens : int
7283 status : int
84+ created_at : Optional [datetime ] = None
85+ updated_at : Optional [datetime ] = None
7386
7487 @model_validator (mode = "after" )
7588 def fill_project_id_from_task_id (self ):
76- """fill by task_id when project_id is None"""
89+ """Fill project_id from task_id when project_id is None"""
7790 if self .project_id is None :
7891 self .project_id = self .task_id
7992 return self
93+
94+ @model_validator (mode = "after" )
95+ def handle_legacy_timestamps (self ):
96+ """Handle legacy records that might not have timestamp fields"""
97+ # For old records without timestamps, we rely on database-level defaults
98+ # The sorting in the controller will handle ordering appropriately
99+ return self
80100
81101
82102class ChatHistoryUpdate (BaseModel ):
0 commit comments