recallrai 0.2.0__py3-none-any.whl → 0.3.1__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 -2
- recallrai/client.py +66 -51
- recallrai/exceptions/__init__.py +21 -9
- recallrai/exceptions/auth.py +2 -5
- recallrai/exceptions/base.py +4 -13
- 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 +38 -5
- recallrai/models/merge_conflict.py +151 -0
- recallrai/models/session.py +64 -28
- recallrai/models/user.py +135 -16
- recallrai/session.py +195 -145
- recallrai/user.py +353 -78
- recallrai/utils/__init__.py +1 -0
- recallrai/utils/http_client.py +38 -23
- recallrai-0.3.1.dist-info/METADATA +902 -0
- recallrai-0.3.1.dist-info/RECORD +23 -0
- {recallrai-0.2.0.dist-info → recallrai-0.3.1.dist-info}/WHEEL +1 -1
- recallrai-0.2.0.dist-info/METADATA +0 -439
- recallrai-0.2.0.dist-info/RECORD +0 -20
|
@@ -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
1
|
"""
|
|
2
2
|
Models used in the SDK.
|
|
3
3
|
"""
|
|
4
|
-
|
|
5
|
-
from .user import
|
|
4
|
+
|
|
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
|
-
"UserModel",
|
|
26
|
+
"UserModel",
|
|
9
27
|
"UserList",
|
|
28
|
+
"UserMemoriesList",
|
|
29
|
+
"UserMessage",
|
|
30
|
+
"UserMessagesList",
|
|
31
|
+
"UserMemoryItem",
|
|
32
|
+
"MemoryVersionInfo",
|
|
33
|
+
"MemoryRelationship",
|
|
34
|
+
|
|
10
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
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Session-related data models for the RecallrAI SDK.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import enum
|
|
5
|
+
import enum
|
|
6
6
|
from datetime import datetime
|
|
7
|
-
from typing import Any, Dict, List
|
|
8
|
-
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List
|
|
9
8
|
from pydantic import BaseModel, Field
|
|
10
|
-
|
|
9
|
+
from ..utils import HTTPClient
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..session import Session
|
|
11
12
|
|
|
12
13
|
class MessageRole(str, enum.Enum):
|
|
13
14
|
"""
|
|
@@ -21,9 +22,9 @@ class Message(BaseModel):
|
|
|
21
22
|
"""
|
|
22
23
|
Represents a message in a conversation session.
|
|
23
24
|
"""
|
|
24
|
-
role: MessageRole = Field(..., description="Role of the message sender (user or assistant)")
|
|
25
|
-
content: str = Field(..., description="Content of the message")
|
|
26
|
-
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.")
|
|
27
28
|
|
|
28
29
|
class Config:
|
|
29
30
|
"""Pydantic configuration."""
|
|
@@ -33,6 +34,27 @@ class Message(BaseModel):
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
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
|
+
|
|
36
58
|
class SessionStatus(str, enum.Enum):
|
|
37
59
|
"""
|
|
38
60
|
Status of a session.
|
|
@@ -46,16 +68,16 @@ class SessionModel(BaseModel):
|
|
|
46
68
|
"""
|
|
47
69
|
Represents a conversation session.
|
|
48
70
|
"""
|
|
49
|
-
session_id:
|
|
50
|
-
status: SessionStatus = Field(..., description="Current status of the session")
|
|
51
|
-
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.")
|
|
52
75
|
|
|
53
76
|
class Config:
|
|
54
77
|
"""Pydantic configuration."""
|
|
55
78
|
frozen = True
|
|
56
79
|
json_encoders = {
|
|
57
80
|
datetime: lambda dt: dt.isoformat(),
|
|
58
|
-
uuid.UUID: lambda id: str(id)
|
|
59
81
|
}
|
|
60
82
|
|
|
61
83
|
@classmethod
|
|
@@ -64,15 +86,20 @@ class SessionModel(BaseModel):
|
|
|
64
86
|
Create a SessionModel instance from an API response.
|
|
65
87
|
|
|
66
88
|
Args:
|
|
67
|
-
data: API response data
|
|
89
|
+
data: API response data.
|
|
68
90
|
|
|
69
91
|
Returns:
|
|
70
|
-
A SessionModel instance
|
|
92
|
+
A SessionModel instance.
|
|
71
93
|
"""
|
|
94
|
+
if "session" in data:
|
|
95
|
+
session_data = data["session"]
|
|
96
|
+
else:
|
|
97
|
+
session_data = data
|
|
72
98
|
return cls(
|
|
73
|
-
session_id=
|
|
74
|
-
status=
|
|
75
|
-
created_at=
|
|
99
|
+
session_id=session_data["session_id"],
|
|
100
|
+
status=session_data["status"],
|
|
101
|
+
created_at=session_data["created_at"],
|
|
102
|
+
metadata=session_data["metadata"],
|
|
76
103
|
)
|
|
77
104
|
|
|
78
105
|
|
|
@@ -80,38 +107,48 @@ class SessionList(BaseModel):
|
|
|
80
107
|
"""
|
|
81
108
|
Represents a paginated list of sessions.
|
|
82
109
|
"""
|
|
83
|
-
sessions: List[
|
|
84
|
-
total: int = Field(..., description="Total number of sessions")
|
|
85
|
-
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.")
|
|
86
113
|
|
|
87
114
|
class Config:
|
|
88
115
|
"""Pydantic configuration."""
|
|
89
116
|
frozen = True
|
|
117
|
+
arbitrary_types_allowed = True
|
|
90
118
|
|
|
91
119
|
@classmethod
|
|
92
|
-
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":
|
|
93
121
|
"""
|
|
94
122
|
Create a SessionList instance from an API response.
|
|
95
123
|
|
|
96
124
|
Args:
|
|
97
|
-
data: API response data
|
|
125
|
+
data: API response data.
|
|
98
126
|
|
|
99
127
|
Returns:
|
|
100
|
-
A SessionList instance
|
|
128
|
+
A SessionList instance.
|
|
101
129
|
"""
|
|
130
|
+
from ..session import Session
|
|
102
131
|
return cls(
|
|
103
|
-
sessions=[
|
|
132
|
+
sessions=[
|
|
133
|
+
Session(http_client, user_id, SessionModel.from_api_response(session)) for session in data["sessions"]
|
|
134
|
+
],
|
|
104
135
|
total=data["total"],
|
|
105
136
|
has_more=data["has_more"],
|
|
106
137
|
)
|
|
107
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"
|
|
108
146
|
|
|
109
147
|
class Context(BaseModel):
|
|
110
148
|
"""
|
|
111
149
|
Represents the context for a session.
|
|
112
150
|
"""
|
|
113
|
-
|
|
114
|
-
context: str = Field(..., description="The context for the session")
|
|
151
|
+
context: str = Field(..., description="The context for the session.")
|
|
115
152
|
|
|
116
153
|
class Config:
|
|
117
154
|
"""Pydantic configuration."""
|
|
@@ -123,12 +160,11 @@ class Context(BaseModel):
|
|
|
123
160
|
Create a Context instance from an API response.
|
|
124
161
|
|
|
125
162
|
Args:
|
|
126
|
-
data: API response data
|
|
163
|
+
data: API response data.
|
|
127
164
|
|
|
128
165
|
Returns:
|
|
129
|
-
A Context instance
|
|
166
|
+
A Context instance.
|
|
130
167
|
"""
|
|
131
168
|
return cls(
|
|
132
|
-
memory_used=data["memory_used"],
|
|
133
169
|
context=data["context"],
|
|
134
170
|
)
|