recallrai 0.1.1__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of recallrai might be problematic. Click here for more details.
- recallrai/__init__.py +2 -5
- recallrai/client.py +67 -55
- recallrai/exceptions/__init__.py +21 -9
- recallrai/exceptions/auth.py +2 -5
- recallrai/exceptions/base.py +5 -16
- recallrai/exceptions/merge_conflicts.py +69 -0
- recallrai/exceptions/network.py +6 -23
- recallrai/exceptions/server.py +17 -40
- recallrai/exceptions/sessions.py +6 -28
- recallrai/exceptions/users.py +16 -31
- recallrai/exceptions/validation.py +2 -9
- recallrai/merge_conflict.py +189 -0
- recallrai/models/__init__.py +41 -8
- recallrai/models/merge_conflict.py +151 -0
- recallrai/models/session.py +67 -35
- recallrai/models/user.py +138 -23
- recallrai/session.py +197 -150
- recallrai/user.py +353 -78
- recallrai/utils/__init__.py +3 -2
- recallrai/utils/http_client.py +38 -23
- recallrai-0.3.0.dist-info/METADATA +902 -0
- recallrai-0.3.0.dist-info/RECORD +23 -0
- {recallrai-0.1.1.dist-info → recallrai-0.3.0.dist-info}/WHEEL +1 -1
- recallrai-0.1.1.dist-info/METADATA +0 -440
- recallrai-0.1.1.dist-info/RECORD +0 -20
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Validation-related exceptions for the RecallrAI SDK.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from typing import Any, Dict, Optional, Union
|
|
6
5
|
from .base import RecallrAIError
|
|
7
6
|
|
|
8
7
|
|
|
@@ -14,11 +13,5 @@ class ValidationError(RecallrAIError):
|
|
|
14
13
|
due to invalid or missing parameters.
|
|
15
14
|
"""
|
|
16
15
|
|
|
17
|
-
def __init__(
|
|
18
|
-
|
|
19
|
-
message: str = "Validation error",
|
|
20
|
-
code: str = "validation_error",
|
|
21
|
-
http_status: int = 422,
|
|
22
|
-
details: Optional[Dict[str, Any]] = None
|
|
23
|
-
):
|
|
24
|
-
super().__init__(message, code, http_status, details)
|
|
16
|
+
def __init__(self, message: str, http_status: int):
|
|
17
|
+
super().__init__(message, http_status)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Merge conflict management functionality for the RecallrAI SDK.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
from .utils import HTTPClient
|
|
7
|
+
from .models import (
|
|
8
|
+
MergeConflictModel,
|
|
9
|
+
MergeConflictStatus,
|
|
10
|
+
MergeConflictAnswer,
|
|
11
|
+
)
|
|
12
|
+
from .exceptions import (
|
|
13
|
+
UserNotFoundError,
|
|
14
|
+
MergeConflictNotFoundError,
|
|
15
|
+
MergeConflictAlreadyResolvedError,
|
|
16
|
+
MergeConflictInvalidQuestionsError,
|
|
17
|
+
MergeConflictMissingAnswersError,
|
|
18
|
+
MergeConflictInvalidAnswerError,
|
|
19
|
+
RecallrAIError
|
|
20
|
+
)
|
|
21
|
+
from logging import getLogger
|
|
22
|
+
|
|
23
|
+
logger = getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MergeConflict:
|
|
27
|
+
"""
|
|
28
|
+
Represents a merge conflict in the RecallrAI system.
|
|
29
|
+
|
|
30
|
+
This class provides methods for inspecting and resolving merge conflicts
|
|
31
|
+
that occur when new memories conflict with existing ones.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
http_client: HTTPClient,
|
|
37
|
+
user_id: str,
|
|
38
|
+
conflict_data: MergeConflictModel,
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Initialize a merge conflict.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
http_client: HTTP client for API communication.
|
|
45
|
+
user_id: User ID who owns this conflict.
|
|
46
|
+
conflict_data: Merge conflict data model.
|
|
47
|
+
"""
|
|
48
|
+
self._http = http_client
|
|
49
|
+
self.user_id = user_id
|
|
50
|
+
self._conflict_data = conflict_data
|
|
51
|
+
|
|
52
|
+
# Expose key properties for easy access
|
|
53
|
+
self.conflict_id = conflict_data.id
|
|
54
|
+
self.status = conflict_data.status
|
|
55
|
+
self.new_memory_content = conflict_data.new_memory_content
|
|
56
|
+
self.conflicting_memories = conflict_data.conflicting_memories
|
|
57
|
+
self.clarifying_questions = conflict_data.clarifying_questions
|
|
58
|
+
self.created_at = conflict_data.created_at
|
|
59
|
+
self.resolved_at = conflict_data.resolved_at
|
|
60
|
+
self.resolution_data = conflict_data.resolution_data
|
|
61
|
+
|
|
62
|
+
def resolve(self, answers: List[MergeConflictAnswer]) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Resolve this merge conflict by providing answers to clarifying questions.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
answers: List of answers to the clarifying questions.
|
|
68
|
+
|
|
69
|
+
Raises:
|
|
70
|
+
UserNotFoundError: If the user is not found.
|
|
71
|
+
MergeConflictNotFoundError: If the merge conflict is not found.
|
|
72
|
+
MergeConflictAlreadyResolvedError: If the conflict is already resolved.
|
|
73
|
+
MergeConflictInvalidQuestionsError: If the provided questions don't match the original questions.
|
|
74
|
+
MergeConflictMissingAnswersError: If not all required questions have been answered.
|
|
75
|
+
MergeConflictInvalidAnswerError: If an answer is not a valid option for its question.
|
|
76
|
+
ValidationError: If the answers are invalid.
|
|
77
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
78
|
+
InternalServerError: If the server encounters an error.
|
|
79
|
+
NetworkError: If there are network issues.
|
|
80
|
+
TimeoutError: If the request times out.
|
|
81
|
+
RecallrAIError: For other API-related errors.
|
|
82
|
+
"""
|
|
83
|
+
if self.status in [MergeConflictStatus.RESOLVED, MergeConflictStatus.FAILED]:
|
|
84
|
+
raise MergeConflictAlreadyResolvedError(
|
|
85
|
+
message=f"Merge conflict {self.conflict_id} is already resolved",
|
|
86
|
+
http_status=400
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Convert answers to the format expected by the API
|
|
90
|
+
answer_data = {
|
|
91
|
+
"question_answers": [
|
|
92
|
+
{
|
|
93
|
+
"question": answer.question,
|
|
94
|
+
"answer": answer.answer,
|
|
95
|
+
"message": answer.message,
|
|
96
|
+
}
|
|
97
|
+
for answer in answers
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
response = self._http.post(
|
|
102
|
+
f"/api/v1/users/{self.user_id}/merge-conflicts/{self.conflict_id}/resolve",
|
|
103
|
+
data={"answers": answer_data},
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
if response.status_code == 404:
|
|
107
|
+
# Check if it's a user not found or conflict not found error
|
|
108
|
+
detail = response.json().get('detail', '')
|
|
109
|
+
if f"User {self.user_id} not found" in detail:
|
|
110
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
111
|
+
else:
|
|
112
|
+
raise MergeConflictNotFoundError(message=detail, http_status=response.status_code)
|
|
113
|
+
elif response.status_code == 400:
|
|
114
|
+
detail = response.json().get('detail', '')
|
|
115
|
+
if "already resolved" in detail:
|
|
116
|
+
raise MergeConflictAlreadyResolvedError(message=detail, http_status=response.status_code)
|
|
117
|
+
elif "Invalid questions provided" in detail:
|
|
118
|
+
raise MergeConflictInvalidQuestionsError(
|
|
119
|
+
message=detail,
|
|
120
|
+
http_status=response.status_code
|
|
121
|
+
)
|
|
122
|
+
elif "Missing answers for the following questions" in detail:
|
|
123
|
+
raise MergeConflictMissingAnswersError(
|
|
124
|
+
message=detail,
|
|
125
|
+
http_status=response.status_code
|
|
126
|
+
)
|
|
127
|
+
elif "Invalid answer" in detail and "for question" in detail:
|
|
128
|
+
raise MergeConflictInvalidAnswerError(
|
|
129
|
+
message=detail,
|
|
130
|
+
http_status=response.status_code
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
raise RecallrAIError(
|
|
134
|
+
message=detail,
|
|
135
|
+
http_status=response.status_code
|
|
136
|
+
)
|
|
137
|
+
elif response.status_code != 200:
|
|
138
|
+
raise RecallrAIError(
|
|
139
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
140
|
+
http_status=response.status_code
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Update the conflict data with the response
|
|
144
|
+
updated_data = MergeConflictModel.from_api_response(response.json())
|
|
145
|
+
self._conflict_data = updated_data
|
|
146
|
+
self.status = updated_data.status
|
|
147
|
+
self.resolved_at = updated_data.resolved_at
|
|
148
|
+
self.resolution_data = updated_data.resolution_data
|
|
149
|
+
|
|
150
|
+
def refresh(self) -> None:
|
|
151
|
+
"""
|
|
152
|
+
Refresh this merge conflict's data from the API.
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
UserNotFoundError: If the user is not found.
|
|
156
|
+
MergeConflictNotFoundError: If the merge conflict is not found.
|
|
157
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
158
|
+
InternalServerError: If the server encounters an error.
|
|
159
|
+
NetworkError: If there are network issues.
|
|
160
|
+
TimeoutError: If the request times out.
|
|
161
|
+
RecallrAIError: For other API-related errors.
|
|
162
|
+
"""
|
|
163
|
+
response = self._http.get(
|
|
164
|
+
f"/api/v1/users/{self.user_id}/merge-conflicts/{self.conflict_id}"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
if response.status_code == 404:
|
|
168
|
+
# Check if it's a user not found or conflict not found error
|
|
169
|
+
detail = response.json().get('detail', '')
|
|
170
|
+
if f"User {self.user_id} not found" in detail:
|
|
171
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
172
|
+
else:
|
|
173
|
+
raise MergeConflictNotFoundError(message=detail, http_status=response.status_code)
|
|
174
|
+
elif response.status_code != 200:
|
|
175
|
+
raise RecallrAIError(
|
|
176
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
177
|
+
http_status=response.status_code
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Update with fresh data
|
|
181
|
+
updated_data = MergeConflictModel.from_api_response(response.json())
|
|
182
|
+
self._conflict_data = updated_data
|
|
183
|
+
self.status = updated_data.status
|
|
184
|
+
self.resolved_at = updated_data.resolved_at
|
|
185
|
+
self.resolution_data = updated_data.resolution_data
|
|
186
|
+
|
|
187
|
+
def __repr__(self) -> str:
|
|
188
|
+
"""Return a string representation of the merge conflict."""
|
|
189
|
+
return f"MergeConflict(id='{self.conflict_id}', status='{self.status}', user_id='{self.user_id}')"
|
recallrai/models/__init__.py
CHANGED
|
@@ -1,16 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"""
|
|
2
|
+
Models used in the SDK.
|
|
3
|
+
"""
|
|
3
4
|
|
|
4
|
-
from .
|
|
5
|
-
|
|
5
|
+
from .user import (
|
|
6
|
+
UserModel,
|
|
7
|
+
UserList,
|
|
8
|
+
UserMemoriesList,
|
|
9
|
+
UserMessage,
|
|
10
|
+
UserMessagesList,
|
|
11
|
+
UserMemoryItem,
|
|
12
|
+
MemoryVersionInfo,
|
|
13
|
+
MemoryRelationship,
|
|
14
|
+
)
|
|
15
|
+
from .session import SessionModel, SessionList, SessionMessagesList, MessageRole, SessionStatus, Context, RecallStrategy
|
|
16
|
+
from .merge_conflict import (
|
|
17
|
+
MergeConflictModel,
|
|
18
|
+
MergeConflictList,
|
|
19
|
+
MergeConflictStatus,
|
|
20
|
+
MergeConflictMemory,
|
|
21
|
+
MergeConflictQuestion,
|
|
22
|
+
MergeConflictAnswer,
|
|
23
|
+
)
|
|
6
24
|
|
|
7
25
|
__all__ = [
|
|
8
|
-
"
|
|
26
|
+
"UserModel",
|
|
9
27
|
"UserList",
|
|
10
|
-
"
|
|
28
|
+
"UserMemoriesList",
|
|
29
|
+
"UserMessage",
|
|
30
|
+
"UserMessagesList",
|
|
31
|
+
"UserMemoryItem",
|
|
32
|
+
"MemoryVersionInfo",
|
|
33
|
+
"MemoryRelationship",
|
|
34
|
+
|
|
35
|
+
"SessionModel",
|
|
11
36
|
"SessionList",
|
|
12
|
-
"
|
|
13
|
-
"Message",
|
|
37
|
+
"SessionMessagesList",
|
|
14
38
|
"MessageRole",
|
|
39
|
+
"SessionStatus",
|
|
15
40
|
"Context",
|
|
41
|
+
"RecallStrategy",
|
|
42
|
+
|
|
43
|
+
"MergeConflictModel",
|
|
44
|
+
"MergeConflictList",
|
|
45
|
+
"MergeConflictStatus",
|
|
46
|
+
"MergeConflictMemory",
|
|
47
|
+
"MergeConflictQuestion",
|
|
48
|
+
"MergeConflictAnswer",
|
|
16
49
|
]
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Merge conflict-related data models for the RecallrAI SDK.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import enum
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
from ..utils import HTTPClient
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from ..merge_conflict import MergeConflict
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MergeConflictStatus(str, enum.Enum):
|
|
16
|
+
"""
|
|
17
|
+
Status of a merge conflict.
|
|
18
|
+
"""
|
|
19
|
+
PENDING = "PENDING"
|
|
20
|
+
IN_QUEUE = "IN_QUEUE"
|
|
21
|
+
RESOLVING = "RESOLVING"
|
|
22
|
+
RESOLVED = "RESOLVED"
|
|
23
|
+
FAILED = "FAILED"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MergeConflictMemory(BaseModel):
|
|
27
|
+
"""
|
|
28
|
+
Represents a memory involved in a merge conflict.
|
|
29
|
+
"""
|
|
30
|
+
content: str = Field(..., description="Content of the conflicting memory.")
|
|
31
|
+
reason: str = Field(..., description="Reason why this memory conflicts.")
|
|
32
|
+
|
|
33
|
+
class Config:
|
|
34
|
+
"""Pydantic configuration."""
|
|
35
|
+
frozen = True
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MergeConflictQuestion(BaseModel):
|
|
39
|
+
"""
|
|
40
|
+
Represents a clarifying question for merge conflict resolution.
|
|
41
|
+
"""
|
|
42
|
+
question: str = Field(..., description="The clarifying question.")
|
|
43
|
+
options: List[str] = Field(..., description="Available answer options.")
|
|
44
|
+
|
|
45
|
+
class Config:
|
|
46
|
+
"""Pydantic configuration."""
|
|
47
|
+
frozen = True
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MergeConflictAnswer(BaseModel):
|
|
51
|
+
"""
|
|
52
|
+
Represents an answer to a clarifying question.
|
|
53
|
+
"""
|
|
54
|
+
question: str = Field(..., description="The question being answered.")
|
|
55
|
+
answer: str = Field(..., description="The selected answer.")
|
|
56
|
+
message: Optional[str] = Field(None, description="Optional additional message.")
|
|
57
|
+
|
|
58
|
+
class Config:
|
|
59
|
+
"""Pydantic configuration."""
|
|
60
|
+
frozen = True
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class MergeConflictModel(BaseModel):
|
|
64
|
+
"""
|
|
65
|
+
Represents a merge conflict in the RecallrAI system.
|
|
66
|
+
"""
|
|
67
|
+
id: str = Field(..., description="Unique identifier for the merge conflict.")
|
|
68
|
+
custom_user_id: str = Field(..., description="User ID who owns this conflict.")
|
|
69
|
+
project_user_session_id: str = Field(..., description="Session ID where the conflict occurred.")
|
|
70
|
+
new_memory_content: str = Field(..., description="New memory content that caused the conflict.")
|
|
71
|
+
conflicting_memories: List[MergeConflictMemory] = Field(..., description="Existing memories that conflict.")
|
|
72
|
+
clarifying_questions: List[MergeConflictQuestion] = Field(..., description="Questions to resolve the conflict.")
|
|
73
|
+
status: MergeConflictStatus = Field(..., description="Current status of the conflict.")
|
|
74
|
+
resolution_data: Optional[Dict[str, Any]] = Field(None, description="Resolution data if resolved.")
|
|
75
|
+
created_at: datetime = Field(..., description="When the conflict was created.")
|
|
76
|
+
resolved_at: Optional[datetime] = Field(None, description="When the conflict was resolved.")
|
|
77
|
+
|
|
78
|
+
class Config:
|
|
79
|
+
"""Pydantic configuration."""
|
|
80
|
+
frozen = True
|
|
81
|
+
json_encoders = {
|
|
82
|
+
datetime: lambda dt: dt.isoformat()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def from_api_response(cls, data: Dict[str, Any]) -> "MergeConflictModel":
|
|
87
|
+
"""
|
|
88
|
+
Create a MergeConflictModel instance from an API response.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
data: API response data.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
A MergeConflictModel instance.
|
|
95
|
+
"""
|
|
96
|
+
conflict_data = data.get("conflict", data)
|
|
97
|
+
|
|
98
|
+
return cls(
|
|
99
|
+
id=conflict_data["id"],
|
|
100
|
+
custom_user_id=conflict_data["custom_user_id"],
|
|
101
|
+
project_user_session_id=conflict_data["project_user_session_id"],
|
|
102
|
+
new_memory_content=conflict_data["new_memory_content"],
|
|
103
|
+
conflicting_memories=[
|
|
104
|
+
MergeConflictMemory(**memory) for memory in conflict_data["conflicting_memories"]
|
|
105
|
+
],
|
|
106
|
+
clarifying_questions=[
|
|
107
|
+
MergeConflictQuestion(**question) for question in conflict_data["clarifying_questions"]
|
|
108
|
+
],
|
|
109
|
+
status=MergeConflictStatus(conflict_data["status"]),
|
|
110
|
+
resolution_data=conflict_data.get("resolution_data"),
|
|
111
|
+
created_at=conflict_data["created_at"],
|
|
112
|
+
resolved_at=conflict_data.get("resolved_at"),
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class MergeConflictList(BaseModel):
|
|
117
|
+
"""
|
|
118
|
+
Represents a paginated list of merge conflicts.
|
|
119
|
+
"""
|
|
120
|
+
conflicts: List["MergeConflict"] = Field(..., description="List of merge conflicts.")
|
|
121
|
+
total: int = Field(..., description="Total number of conflicts.")
|
|
122
|
+
has_more: bool = Field(..., description="Whether there are more conflicts to fetch.")
|
|
123
|
+
|
|
124
|
+
class Config:
|
|
125
|
+
"""Pydantic configuration."""
|
|
126
|
+
frozen = True
|
|
127
|
+
arbitrary_types_allowed = True
|
|
128
|
+
|
|
129
|
+
@classmethod
|
|
130
|
+
def from_api_response(cls, data: Dict[str, Any], http_client: HTTPClient, user_id: str) -> "MergeConflictList":
|
|
131
|
+
"""
|
|
132
|
+
Create a MergeConflictList instance from an API response.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
data: API response data.
|
|
136
|
+
http_client: HTTP client for making API requests.
|
|
137
|
+
user_id: User ID who owns these conflicts.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
A MergeConflictList instance.
|
|
141
|
+
"""
|
|
142
|
+
from ..merge_conflict import MergeConflict
|
|
143
|
+
|
|
144
|
+
return cls(
|
|
145
|
+
conflicts=[
|
|
146
|
+
MergeConflict(http_client, user_id, MergeConflictModel.from_api_response(conflict))
|
|
147
|
+
for conflict in data["conflicts"]
|
|
148
|
+
],
|
|
149
|
+
total=data["total"],
|
|
150
|
+
has_more=data["has_more"],
|
|
151
|
+
)
|
recallrai/models/session.py
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
# Path: recallrai/models/session.py
|
|
2
|
-
# Description: Session data models for the RecallrAI SDK
|
|
3
|
-
|
|
4
1
|
"""
|
|
5
2
|
Session-related data models for the RecallrAI SDK.
|
|
6
3
|
"""
|
|
7
4
|
|
|
8
|
-
import enum
|
|
5
|
+
import enum
|
|
9
6
|
from datetime import datetime
|
|
10
|
-
from typing import Any, Dict, List
|
|
11
|
-
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List
|
|
12
8
|
from pydantic import BaseModel, Field
|
|
13
|
-
|
|
9
|
+
from ..utils import HTTPClient
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..session import Session
|
|
14
12
|
|
|
15
13
|
class MessageRole(str, enum.Enum):
|
|
16
14
|
"""
|
|
@@ -24,9 +22,9 @@ class Message(BaseModel):
|
|
|
24
22
|
"""
|
|
25
23
|
Represents a message in a conversation session.
|
|
26
24
|
"""
|
|
27
|
-
role: MessageRole = Field(..., description="Role of the message sender (user or assistant)")
|
|
28
|
-
content: str = Field(..., description="Content of the message")
|
|
29
|
-
timestamp: datetime = Field(..., description="When the message was sent")
|
|
25
|
+
role: MessageRole = Field(..., description="Role of the message sender (user or assistant).")
|
|
26
|
+
content: str = Field(..., description="Content of the message.")
|
|
27
|
+
timestamp: datetime = Field(..., description="When the message was sent.")
|
|
30
28
|
|
|
31
29
|
class Config:
|
|
32
30
|
"""Pydantic configuration."""
|
|
@@ -36,6 +34,27 @@ class Message(BaseModel):
|
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
|
|
37
|
+
class SessionMessagesList(BaseModel):
|
|
38
|
+
"""
|
|
39
|
+
Represents a paginated list of messages in a session.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
messages: List[Message] = Field(..., description="List of messages in the page.")
|
|
43
|
+
total: int = Field(..., description="Total number of messages in the session.")
|
|
44
|
+
has_more: bool = Field(..., description="Whether there are more messages to fetch.")
|
|
45
|
+
|
|
46
|
+
class Config:
|
|
47
|
+
frozen = True
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def from_api_response(cls, data: Dict[str, Any]) -> "SessionMessagesList":
|
|
51
|
+
return cls(
|
|
52
|
+
messages=[Message(**msg) for msg in data["messages"]],
|
|
53
|
+
total=data["total"],
|
|
54
|
+
has_more=data["has_more"],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
39
58
|
class SessionStatus(str, enum.Enum):
|
|
40
59
|
"""
|
|
41
60
|
Status of a session.
|
|
@@ -45,38 +64,42 @@ class SessionStatus(str, enum.Enum):
|
|
|
45
64
|
PROCESSED = "processed"
|
|
46
65
|
|
|
47
66
|
|
|
48
|
-
class
|
|
67
|
+
class SessionModel(BaseModel):
|
|
49
68
|
"""
|
|
50
69
|
Represents a conversation session.
|
|
51
70
|
"""
|
|
52
|
-
session_id:
|
|
53
|
-
status: SessionStatus = Field(..., description="Current status of the session")
|
|
54
|
-
created_at: datetime = Field(..., description="When the session was created")
|
|
71
|
+
session_id: str = Field(..., description="Unique identifier for the session.")
|
|
72
|
+
status: SessionStatus = Field(..., description="Current status of the session.")
|
|
73
|
+
created_at: datetime = Field(..., description="When the session was created.")
|
|
74
|
+
metadata: Dict[str, Any] = Field(default_factory=dict, description="Optional metadata for the session.")
|
|
55
75
|
|
|
56
76
|
class Config:
|
|
57
77
|
"""Pydantic configuration."""
|
|
58
78
|
frozen = True
|
|
59
79
|
json_encoders = {
|
|
60
80
|
datetime: lambda dt: dt.isoformat(),
|
|
61
|
-
uuid.UUID: lambda id: str(id)
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
@classmethod
|
|
65
|
-
def from_api_response(cls, data: Dict[str, Any]) -> "
|
|
84
|
+
def from_api_response(cls, data: Dict[str, Any]) -> "SessionModel":
|
|
66
85
|
"""
|
|
67
|
-
Create a
|
|
86
|
+
Create a SessionModel instance from an API response.
|
|
68
87
|
|
|
69
88
|
Args:
|
|
70
|
-
data: API response data
|
|
89
|
+
data: API response data.
|
|
71
90
|
|
|
72
91
|
Returns:
|
|
73
|
-
A
|
|
92
|
+
A SessionModel instance.
|
|
74
93
|
"""
|
|
94
|
+
if "session" in data:
|
|
95
|
+
session_data = data["session"]
|
|
96
|
+
else:
|
|
97
|
+
session_data = data
|
|
75
98
|
return cls(
|
|
76
|
-
session_id=
|
|
77
|
-
status=
|
|
78
|
-
created_at=
|
|
79
|
-
|
|
99
|
+
session_id=session_data["session_id"],
|
|
100
|
+
status=session_data["status"],
|
|
101
|
+
created_at=session_data["created_at"],
|
|
102
|
+
metadata=session_data["metadata"],
|
|
80
103
|
)
|
|
81
104
|
|
|
82
105
|
|
|
@@ -84,38 +107,48 @@ class SessionList(BaseModel):
|
|
|
84
107
|
"""
|
|
85
108
|
Represents a paginated list of sessions.
|
|
86
109
|
"""
|
|
87
|
-
sessions: List[Session] = Field(..., description="List of sessions")
|
|
88
|
-
total: int = Field(..., description="Total number of sessions")
|
|
89
|
-
has_more: bool = Field(..., description="Whether there are more sessions to fetch")
|
|
110
|
+
sessions: List["Session"] = Field(..., description="List of sessions.")
|
|
111
|
+
total: int = Field(..., description="Total number of sessions.")
|
|
112
|
+
has_more: bool = Field(..., description="Whether there are more sessions to fetch.")
|
|
90
113
|
|
|
91
114
|
class Config:
|
|
92
115
|
"""Pydantic configuration."""
|
|
93
116
|
frozen = True
|
|
117
|
+
arbitrary_types_allowed = True
|
|
94
118
|
|
|
95
119
|
@classmethod
|
|
96
|
-
def from_api_response(cls, data: Dict[str, Any]) -> "SessionList":
|
|
120
|
+
def from_api_response(cls, data: Dict[str, Any], user_id: str, http_client: HTTPClient) -> "SessionList":
|
|
97
121
|
"""
|
|
98
122
|
Create a SessionList instance from an API response.
|
|
99
123
|
|
|
100
124
|
Args:
|
|
101
|
-
data: API response data
|
|
125
|
+
data: API response data.
|
|
102
126
|
|
|
103
127
|
Returns:
|
|
104
|
-
A SessionList instance
|
|
128
|
+
A SessionList instance.
|
|
105
129
|
"""
|
|
130
|
+
from ..session import Session
|
|
106
131
|
return cls(
|
|
107
|
-
sessions=[
|
|
132
|
+
sessions=[
|
|
133
|
+
Session(http_client, user_id, SessionModel.from_api_response(session)) for session in data["sessions"]
|
|
134
|
+
],
|
|
108
135
|
total=data["total"],
|
|
109
136
|
has_more=data["has_more"],
|
|
110
137
|
)
|
|
111
138
|
|
|
139
|
+
class RecallStrategy(str, enum.Enum):
|
|
140
|
+
"""
|
|
141
|
+
Type of recall strategy.
|
|
142
|
+
"""
|
|
143
|
+
LOW_LATENCY = "low_latency"
|
|
144
|
+
BALANCED = "balanced"
|
|
145
|
+
DEEP = "deep"
|
|
112
146
|
|
|
113
147
|
class Context(BaseModel):
|
|
114
148
|
"""
|
|
115
149
|
Represents the context for a session.
|
|
116
150
|
"""
|
|
117
|
-
|
|
118
|
-
context: str = Field(..., description="The context for the session")
|
|
151
|
+
context: str = Field(..., description="The context for the session.")
|
|
119
152
|
|
|
120
153
|
class Config:
|
|
121
154
|
"""Pydantic configuration."""
|
|
@@ -127,12 +160,11 @@ class Context(BaseModel):
|
|
|
127
160
|
Create a Context instance from an API response.
|
|
128
161
|
|
|
129
162
|
Args:
|
|
130
|
-
data: API response data
|
|
163
|
+
data: API response data.
|
|
131
164
|
|
|
132
165
|
Returns:
|
|
133
|
-
A Context instance
|
|
166
|
+
A Context instance.
|
|
134
167
|
"""
|
|
135
168
|
return cls(
|
|
136
|
-
memory_used=data["memory_used"],
|
|
137
169
|
context=data["context"],
|
|
138
170
|
)
|