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
recallrai/models/user.py
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
# Path: recallrai/models/user.py
|
|
2
|
-
# Description: User data models for the RecallrAI SDK
|
|
3
|
-
|
|
4
1
|
"""
|
|
5
2
|
User-related data models for the RecallrAI SDK.
|
|
6
3
|
"""
|
|
7
4
|
|
|
8
5
|
from datetime import datetime
|
|
9
|
-
from typing import Any, Dict
|
|
10
|
-
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
11
7
|
from pydantic import BaseModel, Field
|
|
8
|
+
from ..utils import HTTPClient
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ..user import User
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
class
|
|
13
|
+
class UserModel(BaseModel):
|
|
15
14
|
"""Represents a user in the RecallrAI system."""
|
|
16
15
|
|
|
17
|
-
user_id: str = Field(..., description="Unique identifier for the user")
|
|
18
|
-
metadata: Dict[str, Any] = Field(
|
|
19
|
-
created_at: datetime = Field(..., description="When the user was created")
|
|
20
|
-
last_active_at: datetime = Field(..., description="When the user was last active")
|
|
16
|
+
user_id: str = Field(..., description="Unique identifier for the user.")
|
|
17
|
+
metadata: Dict[str, Any] = Field(..., description="Custom metadata for the user.")
|
|
18
|
+
created_at: datetime = Field(..., description="When the user was created.")
|
|
19
|
+
last_active_at: datetime = Field(..., description="When the user was last active.")
|
|
21
20
|
|
|
22
21
|
class Config:
|
|
23
22
|
"""Pydantic configuration."""
|
|
@@ -27,21 +26,21 @@ class User(BaseModel):
|
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
@classmethod
|
|
30
|
-
def from_api_response(cls, data: Dict[str, Any]) -> "
|
|
29
|
+
def from_api_response(cls, data: Dict[str, Any]) -> "UserModel":
|
|
31
30
|
"""
|
|
32
|
-
Create a
|
|
31
|
+
Create a UserModel instance from an API response.
|
|
33
32
|
|
|
34
33
|
Args:
|
|
35
|
-
data: API response data
|
|
34
|
+
data: API response data.
|
|
36
35
|
|
|
37
36
|
Returns:
|
|
38
|
-
A
|
|
37
|
+
A UserModel instance.
|
|
39
38
|
"""
|
|
40
39
|
if "user" in data:
|
|
41
40
|
user_data = data["user"]
|
|
42
41
|
else:
|
|
43
42
|
user_data = data
|
|
44
|
-
|
|
43
|
+
|
|
45
44
|
return cls(
|
|
46
45
|
user_id=user_data["user_id"],
|
|
47
46
|
metadata=user_data.get("metadata", {}),
|
|
@@ -52,24 +51,140 @@ class User(BaseModel):
|
|
|
52
51
|
|
|
53
52
|
class UserList(BaseModel):
|
|
54
53
|
"""Represents a paginated list of users."""
|
|
55
|
-
|
|
56
|
-
users:
|
|
57
|
-
total: int = Field(..., description="Total number of users")
|
|
58
|
-
has_more: bool = Field(..., description="Whether there are more users to fetch")
|
|
54
|
+
|
|
55
|
+
users: List["User"] = Field(..., description="List of users.")
|
|
56
|
+
total: int = Field(..., description="Total number of users.")
|
|
57
|
+
has_more: bool = Field(..., description="Whether there are more users to fetch.")
|
|
58
|
+
|
|
59
|
+
class Config:
|
|
60
|
+
arbitrary_types_allowed = True
|
|
59
61
|
|
|
60
62
|
@classmethod
|
|
61
|
-
def from_api_response(cls, data: Dict[str, Any]) -> "UserList":
|
|
63
|
+
def from_api_response(cls, data: Dict[str, Any], http_client: HTTPClient) -> "UserList":
|
|
62
64
|
"""
|
|
63
65
|
Create a UserList instance from an API response.
|
|
64
66
|
|
|
65
67
|
Args:
|
|
66
|
-
data: API response data
|
|
68
|
+
data: API response data.
|
|
67
69
|
|
|
68
70
|
Returns:
|
|
69
|
-
A UserList instance
|
|
71
|
+
A UserList instance.
|
|
70
72
|
"""
|
|
73
|
+
from ..user import User
|
|
71
74
|
return cls(
|
|
72
|
-
users=[
|
|
75
|
+
users=[
|
|
76
|
+
User(http_client, UserModel.from_api_response(user)) for user in data["users"]
|
|
77
|
+
],
|
|
73
78
|
total=data["total"],
|
|
74
79
|
has_more=data["has_more"],
|
|
75
80
|
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class MemoryVersionInfo(BaseModel):
|
|
84
|
+
"""Information about a specific version of a memory."""
|
|
85
|
+
|
|
86
|
+
version_number: int = Field(..., description="Version number (1 = oldest, N = current)")
|
|
87
|
+
content: str = Field(..., description="Content of this version")
|
|
88
|
+
created_at: datetime = Field(..., description="When this version was created")
|
|
89
|
+
expired_at: datetime = Field(..., description="When this version expired")
|
|
90
|
+
expiration_reason: str = Field(..., description="Why this version expired (NewMemoryVersionCreationReason enum)")
|
|
91
|
+
|
|
92
|
+
class Config:
|
|
93
|
+
frozen = True
|
|
94
|
+
json_encoders = {
|
|
95
|
+
datetime: lambda dt: dt.isoformat()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class MemoryRelationship(BaseModel):
|
|
100
|
+
"""Connected memory information."""
|
|
101
|
+
|
|
102
|
+
memory_id: str = Field(..., description="ID of the connected memory")
|
|
103
|
+
content: str = Field(..., description="Brief content for context")
|
|
104
|
+
|
|
105
|
+
class Config:
|
|
106
|
+
frozen = True
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class UserMemoryItem(BaseModel):
|
|
110
|
+
"""Complete memory information with all metadata."""
|
|
111
|
+
|
|
112
|
+
memory_id: str = Field(..., description="ID of the current/latest version")
|
|
113
|
+
categories: List[str] = Field(..., description="Memory categories")
|
|
114
|
+
content: str = Field(..., description="Current version content")
|
|
115
|
+
created_at: datetime = Field(..., description="When the latest version was created")
|
|
116
|
+
|
|
117
|
+
# Version information
|
|
118
|
+
version_number: int = Field(..., description="Which version this is (e.g., 3 means 3rd version)")
|
|
119
|
+
total_versions: int = Field(..., description="How many versions exist total")
|
|
120
|
+
has_previous_versions: bool = Field(..., description="If total_versions > 1")
|
|
121
|
+
|
|
122
|
+
# Version history (only if requested)
|
|
123
|
+
previous_versions: Optional[List[MemoryVersionInfo]] = Field(None, description="Memories connected via prev_version_id")
|
|
124
|
+
|
|
125
|
+
# Relationships (only if requested)
|
|
126
|
+
connected_memories: Optional[List[MemoryRelationship]] = Field(None, description="Memories connected via ProjectUserMemoryConnections")
|
|
127
|
+
|
|
128
|
+
# Merge conflict info
|
|
129
|
+
merge_conflict_in_progress: bool = Field(..., description="Whether a merge conflict is in progress")
|
|
130
|
+
|
|
131
|
+
# Session info
|
|
132
|
+
session_id: str = Field(..., description="Which session created this version")
|
|
133
|
+
|
|
134
|
+
class Config:
|
|
135
|
+
frozen = True
|
|
136
|
+
json_encoders = {
|
|
137
|
+
datetime: lambda dt: dt.isoformat()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class UserMemoriesList(BaseModel):
|
|
142
|
+
"""Represents a paginated list of user memories."""
|
|
143
|
+
|
|
144
|
+
items: List[UserMemoryItem]
|
|
145
|
+
total: int
|
|
146
|
+
has_more: bool
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def from_api_response(cls, data: Dict[str, Any]) -> "UserMemoriesList":
|
|
150
|
+
return cls(
|
|
151
|
+
items=[UserMemoryItem(**item) for item in data["items"]],
|
|
152
|
+
total=data["total"],
|
|
153
|
+
has_more=data["has_more"],
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class UserMessage(BaseModel):
|
|
158
|
+
"""Represents a single message from a user's conversation history."""
|
|
159
|
+
|
|
160
|
+
role: str = Field(..., description="Role of the message sender (user or assistant).")
|
|
161
|
+
content: str = Field(..., description="Content of the message.")
|
|
162
|
+
timestamp: datetime = Field(..., description="When the message was sent.")
|
|
163
|
+
session_id: str = Field(..., description="ID of the session this message belongs to.")
|
|
164
|
+
|
|
165
|
+
class Config:
|
|
166
|
+
frozen = True
|
|
167
|
+
json_encoders = {
|
|
168
|
+
datetime: lambda dt: dt.isoformat()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class UserMessagesList(BaseModel):
|
|
173
|
+
"""Represents a list of user messages."""
|
|
174
|
+
|
|
175
|
+
messages: List[UserMessage] = Field(..., description="List of user messages.")
|
|
176
|
+
|
|
177
|
+
@classmethod
|
|
178
|
+
def from_api_response(cls, data: Dict[str, Any]) -> "UserMessagesList":
|
|
179
|
+
"""
|
|
180
|
+
Create a UserMessagesList instance from an API response.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
data: API response data.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
A UserMessagesList instance.
|
|
187
|
+
"""
|
|
188
|
+
return cls(
|
|
189
|
+
messages=[UserMessage(**message) for message in data["messages"]]
|
|
190
|
+
)
|
recallrai/session.py
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
# Path: recallrai/session.py
|
|
2
|
-
# Description: Session management class for the RecallrAI SDK
|
|
3
|
-
|
|
4
1
|
"""
|
|
5
2
|
Session management functionality for the RecallrAI SDK.
|
|
6
3
|
"""
|
|
7
4
|
|
|
8
|
-
from typing import
|
|
5
|
+
from typing import Optional, Dict, Any
|
|
9
6
|
from .utils import HTTPClient
|
|
10
7
|
from .models import (
|
|
11
8
|
Context,
|
|
12
|
-
|
|
9
|
+
SessionMessagesList,
|
|
10
|
+
SessionModel,
|
|
13
11
|
SessionStatus,
|
|
14
|
-
MessageRole
|
|
12
|
+
MessageRole,
|
|
13
|
+
RecallStrategy,
|
|
15
14
|
)
|
|
16
15
|
from .exceptions import (
|
|
17
16
|
UserNotFoundError,
|
|
@@ -35,245 +34,293 @@ class Session:
|
|
|
35
34
|
self,
|
|
36
35
|
http_client: HTTPClient,
|
|
37
36
|
user_id: str,
|
|
38
|
-
|
|
37
|
+
session_data: SessionModel,
|
|
39
38
|
):
|
|
40
39
|
"""
|
|
41
40
|
Initialize a session.
|
|
42
41
|
|
|
43
42
|
Args:
|
|
44
|
-
http_client: HTTP client for API communication
|
|
45
|
-
user_id: ID of the user who owns this session
|
|
46
|
-
|
|
43
|
+
http_client: HTTP client for API communication.
|
|
44
|
+
user_id: ID of the user who owns this session.
|
|
45
|
+
session_data: Initial session data from the API.
|
|
47
46
|
"""
|
|
48
47
|
self._http = http_client
|
|
49
|
-
self.
|
|
50
|
-
self.
|
|
48
|
+
self._user_id = user_id
|
|
49
|
+
self._session_data = session_data
|
|
50
|
+
self.session_id = self._session_data.session_id
|
|
51
|
+
self.status = self._session_data.status
|
|
52
|
+
self.created_at = self._session_data.created_at
|
|
53
|
+
self.metadata = self._session_data.metadata
|
|
51
54
|
|
|
52
|
-
def
|
|
55
|
+
def add_message(self, role: MessageRole, content: str) -> None:
|
|
53
56
|
"""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Args:
|
|
57
|
-
message: Content of the user message
|
|
58
|
-
|
|
59
|
-
Raises:
|
|
60
|
-
UserNotFoundError: If the user is not found
|
|
61
|
-
SessionNotFoundError: If the session is not found
|
|
62
|
-
InvalidSessionStateError: If the session is already processed or processing
|
|
63
|
-
AuthenticationError: If the API key or project ID is invalid
|
|
64
|
-
InternalServerError: If the server encounters an error
|
|
65
|
-
NetworkError: If there are network issues
|
|
66
|
-
TimeoutError: If the request times out
|
|
67
|
-
RecallrAIError: For other API-related errors
|
|
68
|
-
"""
|
|
69
|
-
self._add_message(message, MessageRole.USER)
|
|
70
|
-
|
|
71
|
-
def add_assistant_message(self, message: str) -> None:
|
|
72
|
-
"""
|
|
73
|
-
Add an assistant message to the session.
|
|
57
|
+
Internal helper to add a message to the session.
|
|
74
58
|
|
|
75
59
|
Args:
|
|
76
|
-
|
|
60
|
+
role: Role of the message sender.
|
|
61
|
+
content: Content of the message.
|
|
77
62
|
|
|
78
63
|
Raises:
|
|
79
|
-
UserNotFoundError: If the user is not found
|
|
80
|
-
SessionNotFoundError: If the session is not found
|
|
81
|
-
InvalidSessionStateError: If the session is already processed or processing
|
|
82
|
-
AuthenticationError: If the API key or project ID is invalid
|
|
83
|
-
InternalServerError: If the server encounters an error
|
|
84
|
-
NetworkError: If there are network issues
|
|
85
|
-
TimeoutError: If the request times out
|
|
86
|
-
RecallrAIError: For other API-related errors
|
|
87
|
-
"""
|
|
88
|
-
self._add_message(message, MessageRole.ASSISTANT)
|
|
89
|
-
|
|
90
|
-
def _add_message(self, message: str, role: MessageRole) -> None:
|
|
91
|
-
"""
|
|
92
|
-
Internal helper to add a message to the session.
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
message: Content of the message
|
|
96
|
-
role: Role of the message sender
|
|
97
|
-
|
|
98
|
-
Raises:
|
|
99
|
-
UserNotFoundError: If the user is not found
|
|
100
|
-
SessionNotFoundError: If the session is not found
|
|
101
|
-
InvalidSessionStateError: If the session is already processed or processing
|
|
102
|
-
AuthenticationError: If the API key or project ID is invalid
|
|
103
|
-
InternalServerError: If the server encounters an error
|
|
104
|
-
NetworkError: If there are network issues
|
|
105
|
-
TimeoutError: If the request times out
|
|
106
|
-
RecallrAIError: For other API-related errors
|
|
64
|
+
UserNotFoundError: If the user is not found.
|
|
65
|
+
SessionNotFoundError: If the session is not found.
|
|
66
|
+
InvalidSessionStateError: If the session is already processed or processing.
|
|
67
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
68
|
+
InternalServerError: If the server encounters an error.
|
|
69
|
+
NetworkError: If there are network issues.
|
|
70
|
+
TimeoutError: If the request times out.
|
|
71
|
+
RecallrAIError: For other API-related errors.
|
|
107
72
|
"""
|
|
108
73
|
response = self._http.post(
|
|
109
|
-
f"/api/v1/users/{self.
|
|
110
|
-
data={"message":
|
|
74
|
+
f"/api/v1/users/{self._user_id}/sessions/{self.session_id}/add-message",
|
|
75
|
+
data={"message": content, "role": role.value},
|
|
111
76
|
)
|
|
112
|
-
|
|
77
|
+
|
|
113
78
|
if response.status_code == 404:
|
|
114
79
|
# Check if it's a user not found or session not found error
|
|
115
80
|
detail = response.json().get('detail', '')
|
|
116
|
-
if f"User {self.
|
|
117
|
-
raise UserNotFoundError(
|
|
81
|
+
if f"User {self._user_id} not found" in detail:
|
|
82
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
118
83
|
else:
|
|
119
|
-
raise SessionNotFoundError(
|
|
84
|
+
raise SessionNotFoundError(message=detail, http_status=response.status_code)
|
|
120
85
|
elif response.status_code == 400:
|
|
86
|
+
detail = response.json().get('detail', f"Cannot add message to session with status {self.status}")
|
|
121
87
|
raise InvalidSessionStateError(
|
|
122
|
-
message=
|
|
88
|
+
message=detail,
|
|
89
|
+
http_status=response.status_code
|
|
123
90
|
)
|
|
124
91
|
elif response.status_code != 200:
|
|
125
92
|
raise RecallrAIError(
|
|
126
|
-
message=
|
|
93
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
127
94
|
http_status=response.status_code
|
|
128
95
|
)
|
|
129
96
|
|
|
130
|
-
def get_context(
|
|
97
|
+
def get_context(
|
|
98
|
+
self,
|
|
99
|
+
recall_strategy: RecallStrategy = RecallStrategy.BALANCED,
|
|
100
|
+
min_top_k: int = 15,
|
|
101
|
+
max_top_k: int = 50,
|
|
102
|
+
memories_threshold: float = 0.6,
|
|
103
|
+
summaries_threshold: float = 0.5,
|
|
104
|
+
last_n_messages: Optional[int] = None,
|
|
105
|
+
last_n_summaries: Optional[int] = None,
|
|
106
|
+
timezone: Optional[str] = None
|
|
107
|
+
) -> Context:
|
|
131
108
|
"""
|
|
132
109
|
Get the current context for this session.
|
|
133
110
|
|
|
134
|
-
|
|
135
|
-
|
|
111
|
+
Args:
|
|
112
|
+
recall_strategy: The type of recall strategy to use.
|
|
113
|
+
min_top_k: Minimum number of memories to return.
|
|
114
|
+
max_top_k: Maximum number of memories to return.
|
|
115
|
+
memories_threshold: Similarity threshold for memories.
|
|
116
|
+
summaries_threshold: Similarity threshold for summaries.
|
|
117
|
+
last_n_messages: Number of last messages to include in context.
|
|
118
|
+
last_n_summaries: Number of last summaries to include in context.
|
|
119
|
+
timezone: Timezone for formatting timestamps (e.g., 'America/New_York'). None for UTC.
|
|
136
120
|
|
|
137
121
|
Returns:
|
|
138
|
-
Context information with the memory text and whether memory was used
|
|
122
|
+
Context information with the memory text and whether memory was used.
|
|
139
123
|
|
|
140
124
|
Raises:
|
|
141
|
-
UserNotFoundError: If the user is not found
|
|
142
|
-
SessionNotFoundError: If the session is not found
|
|
143
|
-
AuthenticationError: If the API key or project ID is invalid
|
|
144
|
-
InternalServerError: If the server encounters an error
|
|
145
|
-
NetworkError: If there are network issues
|
|
146
|
-
TimeoutError: If the request times out
|
|
147
|
-
RecallrAIError: For other API-related errors
|
|
125
|
+
UserNotFoundError: If the user is not found.
|
|
126
|
+
SessionNotFoundError: If the session is not found.
|
|
127
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
128
|
+
InternalServerError: If the server encounters an error.
|
|
129
|
+
NetworkError: If there are network issues.
|
|
130
|
+
TimeoutError: If the request times out.
|
|
131
|
+
RecallrAIError: For other API-related errors.
|
|
148
132
|
"""
|
|
133
|
+
params = {
|
|
134
|
+
"recall_strategy": recall_strategy.value,
|
|
135
|
+
"min_top_k": min_top_k,
|
|
136
|
+
"max_top_k": max_top_k,
|
|
137
|
+
"memories_threshold": memories_threshold,
|
|
138
|
+
"summaries_threshold": summaries_threshold,
|
|
139
|
+
}
|
|
140
|
+
if last_n_messages is not None:
|
|
141
|
+
params["last_n_messages"] = last_n_messages
|
|
142
|
+
if last_n_summaries is not None:
|
|
143
|
+
params["last_n_summaries"] = last_n_summaries
|
|
144
|
+
if timezone is not None:
|
|
145
|
+
params["timezone"] = timezone
|
|
146
|
+
|
|
149
147
|
response = self._http.get(
|
|
150
|
-
f"/api/v1/users/{self.
|
|
148
|
+
f"/api/v1/users/{self._user_id}/sessions/{self.session_id}/context",
|
|
149
|
+
params=params,
|
|
151
150
|
)
|
|
152
|
-
|
|
151
|
+
|
|
153
152
|
if response.status_code == 404:
|
|
154
153
|
# Check if it's a user not found or session not found error
|
|
155
154
|
detail = response.json().get('detail', '')
|
|
156
|
-
if f"User {self.
|
|
157
|
-
raise UserNotFoundError(
|
|
155
|
+
if f"User {self._user_id} not found" in detail:
|
|
156
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
158
157
|
else:
|
|
159
|
-
raise SessionNotFoundError(
|
|
158
|
+
raise SessionNotFoundError(message=detail, http_status=response.status_code)
|
|
160
159
|
elif response.status_code != 200:
|
|
161
160
|
raise RecallrAIError(
|
|
162
|
-
message=
|
|
161
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
163
162
|
http_status=response.status_code
|
|
164
163
|
)
|
|
165
|
-
status
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
logger.warning("Cannot add message to a session that is currently being processed")
|
|
164
|
+
if self.status == SessionStatus.PROCESSED:
|
|
165
|
+
logger.warning("You are trying to get context for a processed session. Why do you need it?")
|
|
166
|
+
elif self.status == SessionStatus.PROCESSING:
|
|
167
|
+
logger.warning("You are trying to get context for a processing session. Why do you need it?")
|
|
170
168
|
return Context.from_api_response(response.json())
|
|
171
169
|
|
|
172
|
-
def
|
|
170
|
+
def update(self, new_metadata: Optional[Dict[str, Any]] = None) -> None:
|
|
173
171
|
"""
|
|
174
|
-
|
|
172
|
+
Update the session's metadata.
|
|
175
173
|
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
Args:
|
|
175
|
+
new_metadata: New metadata to associate with the session.
|
|
178
176
|
|
|
179
177
|
Raises:
|
|
180
|
-
UserNotFoundError: If the user is not found
|
|
181
|
-
SessionNotFoundError: If the session is not found
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
RecallrAIError: For other API-related errors
|
|
178
|
+
UserNotFoundError: If the user is not found.
|
|
179
|
+
SessionNotFoundError: If the session is not found.
|
|
180
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
181
|
+
InternalServerError: If the server encounters an error.
|
|
182
|
+
NetworkError: If there are network issues.
|
|
183
|
+
TimeoutError: If the request times out.
|
|
184
|
+
RecallrAIError: For other API-related errors.
|
|
188
185
|
"""
|
|
189
|
-
response = self._http.
|
|
190
|
-
f"/api/v1/users/{self.
|
|
186
|
+
response = self._http.put(
|
|
187
|
+
f"/api/v1/users/{self._user_id}/sessions/{self.session_id}",
|
|
188
|
+
data={"new_metadata": new_metadata},
|
|
191
189
|
)
|
|
192
|
-
|
|
190
|
+
|
|
193
191
|
if response.status_code == 404:
|
|
194
192
|
# Check if it's a user not found or session not found error
|
|
195
193
|
detail = response.json().get('detail', '')
|
|
196
|
-
if f"User {self.
|
|
197
|
-
raise UserNotFoundError(
|
|
194
|
+
if f"User {self._user_id} not found" in detail:
|
|
195
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
198
196
|
else:
|
|
199
|
-
raise SessionNotFoundError(
|
|
200
|
-
elif response.status_code == 400:
|
|
201
|
-
raise InvalidSessionStateError(
|
|
202
|
-
message=f"{response.json().get('detail', f'Cannot process session with status {self.get_status()}')}",
|
|
203
|
-
)
|
|
197
|
+
raise SessionNotFoundError(message=detail, http_status=response.status_code)
|
|
204
198
|
elif response.status_code != 200:
|
|
205
199
|
raise RecallrAIError(
|
|
206
|
-
message=
|
|
200
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
207
201
|
http_status=response.status_code
|
|
208
202
|
)
|
|
203
|
+
|
|
204
|
+
updated_data = SessionModel.from_api_response(response.json())
|
|
205
|
+
self.metadata = updated_data.metadata
|
|
209
206
|
|
|
210
|
-
def
|
|
207
|
+
def refresh(self) -> None:
|
|
211
208
|
"""
|
|
212
|
-
|
|
209
|
+
Refresh the session data from the API.
|
|
213
210
|
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
This method updates the local session data to reflect any changes
|
|
212
|
+
that may have occurred on the server.
|
|
216
213
|
|
|
217
214
|
Raises:
|
|
218
|
-
UserNotFoundError: If the user is not found
|
|
219
|
-
SessionNotFoundError: If the session is not found
|
|
220
|
-
AuthenticationError: If the API key or project ID is invalid
|
|
221
|
-
InternalServerError: If the server encounters an error
|
|
222
|
-
NetworkError: If there are network issues
|
|
223
|
-
TimeoutError: If the request times out
|
|
224
|
-
RecallrAIError: For other API-related errors
|
|
215
|
+
UserNotFoundError: If the user is not found.
|
|
216
|
+
SessionNotFoundError: If the session is not found.
|
|
217
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
218
|
+
InternalServerError: If the server encounters an error.
|
|
219
|
+
NetworkError: If there are network issues.
|
|
220
|
+
TimeoutError: If the request times out.
|
|
221
|
+
RecallrAIError: For other API-related errors.
|
|
225
222
|
"""
|
|
226
223
|
response = self._http.get(
|
|
227
|
-
f"/api/v1/users/{self.
|
|
224
|
+
f"/api/v1/users/{self._user_id}/sessions/{self.session_id}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
if response.status_code == 404:
|
|
228
|
+
# Check if it's a user not found or session not found error
|
|
229
|
+
detail = response.json().get('detail', '')
|
|
230
|
+
if f"User {self._user_id} not found" in detail:
|
|
231
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
232
|
+
else:
|
|
233
|
+
raise SessionNotFoundError(message=detail, http_status=response.status_code)
|
|
234
|
+
elif response.status_code != 200:
|
|
235
|
+
raise RecallrAIError(
|
|
236
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
237
|
+
http_status=response.status_code
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
self._session_data = SessionModel.from_api_response(response.json())
|
|
241
|
+
self.status = self._session_data.status
|
|
242
|
+
self.created_at = self._session_data.created_at
|
|
243
|
+
self.metadata = self._session_data.metadata
|
|
244
|
+
|
|
245
|
+
def process(self) -> None:
|
|
246
|
+
"""
|
|
247
|
+
Process the session to update the user's memory.
|
|
248
|
+
|
|
249
|
+
This method triggers the processing of the conversation to extract and update
|
|
250
|
+
the user's memory.
|
|
251
|
+
|
|
252
|
+
Raises:
|
|
253
|
+
UserNotFoundError: If the user is not found.
|
|
254
|
+
SessionNotFoundError: If the session is not found.
|
|
255
|
+
InvalidSessionStateError: If the session is already processed or being processed.
|
|
256
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
257
|
+
InternalServerError: If the server encounters an error.
|
|
258
|
+
NetworkError: If there are network issues.
|
|
259
|
+
TimeoutError: If the request times out.
|
|
260
|
+
RecallrAIError: For other API-related errors.
|
|
261
|
+
"""
|
|
262
|
+
response = self._http.post(
|
|
263
|
+
f"/api/v1/users/{self._user_id}/sessions/{self.session_id}/process"
|
|
228
264
|
)
|
|
229
265
|
|
|
230
266
|
if response.status_code == 404:
|
|
231
267
|
# Check if it's a user not found or session not found error
|
|
232
268
|
detail = response.json().get('detail', '')
|
|
233
|
-
if f"User {self.
|
|
234
|
-
raise UserNotFoundError(
|
|
269
|
+
if f"User {self._user_id} not found" in detail:
|
|
270
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
235
271
|
else:
|
|
236
|
-
raise SessionNotFoundError(
|
|
272
|
+
raise SessionNotFoundError(message=detail, http_status=response.status_code)
|
|
273
|
+
elif response.status_code == 400:
|
|
274
|
+
detail = response.json().get('detail', f'Cannot process session with status {self.status}')
|
|
275
|
+
raise InvalidSessionStateError(
|
|
276
|
+
message=detail,
|
|
277
|
+
http_status=response.status_code
|
|
278
|
+
)
|
|
237
279
|
elif response.status_code != 200:
|
|
238
280
|
raise RecallrAIError(
|
|
239
|
-
message=
|
|
281
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
240
282
|
http_status=response.status_code
|
|
241
283
|
)
|
|
242
|
-
|
|
243
|
-
return SessionStatus(response.json()["status"])
|
|
244
284
|
|
|
245
|
-
def get_messages(
|
|
285
|
+
def get_messages(
|
|
286
|
+
self,
|
|
287
|
+
offset: int = 0,
|
|
288
|
+
limit: int = 50,
|
|
289
|
+
) -> SessionMessagesList:
|
|
246
290
|
"""
|
|
247
291
|
Get all messages in the session.
|
|
248
292
|
|
|
249
293
|
Returns:
|
|
250
|
-
|
|
294
|
+
Paginated list of messages in the session.
|
|
251
295
|
|
|
252
296
|
Raises:
|
|
253
|
-
UserNotFoundError: If the user is not found
|
|
254
|
-
SessionNotFoundError: If the session is not found
|
|
255
|
-
AuthenticationError: If the API key or project ID is invalid
|
|
256
|
-
InternalServerError: If the server encounters an error
|
|
257
|
-
NetworkError: If there are network issues
|
|
258
|
-
TimeoutError: If the request times out
|
|
259
|
-
RecallrAIError: For other API-related errors
|
|
297
|
+
UserNotFoundError: If the user is not found.
|
|
298
|
+
SessionNotFoundError: If the session is not found.
|
|
299
|
+
AuthenticationError: If the API key or project ID is invalid.
|
|
300
|
+
InternalServerError: If the server encounters an error.
|
|
301
|
+
NetworkError: If there are network issues.
|
|
302
|
+
TimeoutError: If the request times out.
|
|
303
|
+
RecallrAIError: For other API-related errors.
|
|
260
304
|
"""
|
|
261
305
|
response = self._http.get(
|
|
262
|
-
f"/api/v1/users/{self.
|
|
306
|
+
f"/api/v1/users/{self._user_id}/sessions/{self.session_id}/messages",
|
|
307
|
+
params={"offset": offset, "limit": limit},
|
|
263
308
|
)
|
|
264
309
|
|
|
265
310
|
if response.status_code == 404:
|
|
266
311
|
# Check if it's a user not found or session not found error
|
|
267
312
|
detail = response.json().get('detail', '')
|
|
268
|
-
if f"User {self.
|
|
269
|
-
raise UserNotFoundError(
|
|
313
|
+
if f"User {self._user_id} not found" in detail:
|
|
314
|
+
raise UserNotFoundError(message=detail, http_status=response.status_code)
|
|
270
315
|
else:
|
|
271
|
-
raise SessionNotFoundError(
|
|
316
|
+
raise SessionNotFoundError(message=detail, http_status=response.status_code)
|
|
272
317
|
elif response.status_code != 200:
|
|
273
318
|
raise RecallrAIError(
|
|
274
|
-
message=
|
|
319
|
+
message=response.json().get('detail', 'Unknown error'),
|
|
275
320
|
http_status=response.status_code
|
|
276
321
|
)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
322
|
+
|
|
323
|
+
return SessionMessagesList.from_api_response(response.json())
|
|
324
|
+
|
|
325
|
+
def __repr__(self) -> str:
|
|
326
|
+
return f"<Session id={self.session_id} user_id={self._user_id} status={self.status}>"
|