File size: 4,736 Bytes
a8a2cf5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c77cd6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""Data models and schemas for the application."""

from pydantic import BaseModel, Field, EmailStr, validator
from typing import Optional
from datetime import datetime

# ===== USER SCHEMAS =====

class UserCreate(BaseModel):
    """What we need to create a user."""
    email: EmailStr
    name: str = Field(..., min_length=1, max_length=100)
    password: str = Field(..., min_length=8)

class UserLogin(BaseModel):
    """What we need to login."""
    email: EmailStr
    password: str

class UserResponse(BaseModel):
    """What we return about a user."""
    id: int
    email: str
    name: str
    created_at: datetime
    
    class Config:
        from_attributes = True

class UserUpdate(BaseModel):
    """What can be updated."""
    name: Optional[str] = Field(None, min_length=1, max_length=100)

# ===== AUTH SCHEMAS =====

class Token(BaseModel):
    """JWT token response."""
    access_token: str
    token_type: str = "bearer"

class TokenData(BaseModel):
    """Data encoded in the token."""
    user_id: int
    email: str

# ===== CHAT SCHEMAS =====

class Message(BaseModel):
    """A chat message."""
    id: Optional[int] = None
    conversation_id: int
    sender_id: int
    content: str
    created_at: Optional[datetime] = None

class Conversation(BaseModel):
    """A conversation thread."""
    id: Optional[int] = None
    user_id: int
    title: str
    created_at: Optional[datetime] = None

# ===== AI QUERY SCHEMAS =====

class QueryRequest(BaseModel):
    """Request for AI query."""
    conversation_id: Optional[str] = Field(
        default=None,
        max_length=128,
        description="Optional conversation/session id used for chat memory and per-thread RAG"
    )
    query: str = Field(
        ..., 
        min_length=1, 
        max_length=1000, 
        description="The question or prompt to send to the AI"
    )
    
    @validator('query')
    def validate_query(cls, v):
        if not v.strip():
            raise ValueError("Query cannot be empty")
        # Basic sanitization - remove potential script tags
        v = v.replace("<script", "").replace("</script>", "")
        return v.strip()

    @validator('conversation_id')
    def validate_conversation_id(cls, v):
        if v is None:
            return None
        v = str(v).strip()
        return v or None

class QueryResponse(BaseModel):
    """Response from AI query."""
    success: bool
    response: Optional[str] = None
    error: Optional[str] = None
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    requires_auth: bool = False  # True if Google authentication is needed
    auth_url: Optional[str] = None  # Google OAuth URL if authentication is required

class HealthCheckResponse(BaseModel):
    """Health check response."""
    status: str  # "healthy", "degraded", "unhealthy"
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    version: str = "1.0.0"
    components: dict = {}
# ===== CONVERSATION MANAGEMENT SCHEMAS =====

class MessageResponse(BaseModel):
    """Response format for a single message."""
    id: int
    sender_id: int
    content: str
    created_at: datetime
    
    class Config:
        from_attributes = True

class ConversationListResponse(BaseModel):
    """Brief conversation info for listing."""
    id: int
    title: Optional[str] = None
    created_at: datetime
    last_message_at: datetime
    message_count: int
    
    class Config:
        from_attributes = True

class ConversationDetailResponse(BaseModel):
    """Full conversation with all messages."""
    id: int
    title: Optional[str] = None
    created_at: datetime
    last_message_at: datetime
    messages: list[MessageResponse]
    
    class Config:
        from_attributes = True

class ChatRequest(BaseModel):
    """Chat message request."""
    conversation_id: Optional[int] = Field(
        None,
        description="Existing conversation ID, or None to create new conversation"
    )
    query: str = Field(
        ...,
        min_length=1,
        max_length=2000,
        description="User's message or query"
    )
    
    @validator('query')
    def validate_query(cls, v):
        if not v.strip():
            raise ValueError("Query cannot be empty")
        return v.strip()

class ChatResponse(BaseModel):
    """Chat message response."""
    conversation_id: int
    response: str
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    
    class Config:
        from_attributes = True

class PaginatedConversationsResponse(BaseModel):
    """Paginated list of conversations."""
    conversations: list[ConversationListResponse]
    total: int
    skip: int
    limit: int
    
    class Config:
        from_attributes = True