recallrai 0.1.0__py3-none-any.whl → 0.2.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.

@@ -1,13 +1,10 @@
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
5
  import enum, uuid
9
6
  from datetime import datetime
10
- from typing import Any, Dict, List, Optional
7
+ from typing import Any, Dict, List
11
8
 
12
9
  from pydantic import BaseModel, Field
13
10
 
@@ -45,7 +42,7 @@ class SessionStatus(str, enum.Enum):
45
42
  PROCESSED = "processed"
46
43
 
47
44
 
48
- class Session(BaseModel):
45
+ class SessionModel(BaseModel):
49
46
  """
50
47
  Represents a conversation session.
51
48
  """
@@ -62,21 +59,20 @@ class Session(BaseModel):
62
59
  }
63
60
 
64
61
  @classmethod
65
- def from_api_response(cls, data: Dict[str, Any]) -> "Session":
62
+ def from_api_response(cls, data: Dict[str, Any]) -> "SessionModel":
66
63
  """
67
- Create a Session instance from an API response.
64
+ Create a SessionModel instance from an API response.
68
65
 
69
66
  Args:
70
67
  data: API response data
71
68
 
72
69
  Returns:
73
- A Session instance
70
+ A SessionModel instance
74
71
  """
75
72
  return cls(
76
73
  session_id=data["session_id"],
77
74
  status=data.get("status", SessionStatus.PENDING),
78
75
  created_at=data.get("created_at", datetime.now()),
79
- messages=None
80
76
  )
81
77
 
82
78
 
@@ -84,7 +80,7 @@ class SessionList(BaseModel):
84
80
  """
85
81
  Represents a paginated list of sessions.
86
82
  """
87
- sessions: List[Session] = Field(..., description="List of sessions")
83
+ sessions: List[SessionModel] = Field(..., description="List of sessions")
88
84
  total: int = Field(..., description="Total number of sessions")
89
85
  has_more: bool = Field(..., description="Whether there are more sessions to fetch")
90
86
 
@@ -104,7 +100,7 @@ class SessionList(BaseModel):
104
100
  A SessionList instance
105
101
  """
106
102
  return cls(
107
- sessions=[Session.from_api_response(session) for session in data["sessions"]],
103
+ sessions=[SessionModel.from_api_response(session) for session in data["sessions"]],
108
104
  total=data["total"],
109
105
  has_more=data["has_more"],
110
106
  )
recallrai/models/user.py CHANGED
@@ -1,17 +1,13 @@
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
6
  from typing import Any, Dict
10
-
11
7
  from pydantic import BaseModel, Field
12
8
 
13
9
 
14
- class User(BaseModel):
10
+ class UserModel(BaseModel):
15
11
  """Represents a user in the RecallrAI system."""
16
12
 
17
13
  user_id: str = Field(..., description="Unique identifier for the user")
@@ -27,15 +23,15 @@ class User(BaseModel):
27
23
  }
28
24
 
29
25
  @classmethod
30
- def from_api_response(cls, data: Dict[str, Any]) -> "User":
26
+ def from_api_response(cls, data: Dict[str, Any]) -> "UserModel":
31
27
  """
32
- Create a User instance from an API response.
28
+ Create a UserModel instance from an API response.
33
29
 
34
30
  Args:
35
31
  data: API response data
36
32
 
37
33
  Returns:
38
- A User instance
34
+ A UserModel instance
39
35
  """
40
36
  if "user" in data:
41
37
  user_data = data["user"]
@@ -53,7 +49,7 @@ class User(BaseModel):
53
49
  class UserList(BaseModel):
54
50
  """Represents a paginated list of users."""
55
51
 
56
- users: list[User] = Field(..., description="List of users")
52
+ users: list[UserModel] = Field(..., description="List of users")
57
53
  total: int = Field(..., description="Total number of users")
58
54
  has_more: bool = Field(..., description="Whether there are more users to fetch")
59
55
 
@@ -69,7 +65,7 @@ class UserList(BaseModel):
69
65
  A UserList instance
70
66
  """
71
67
  return cls(
72
- users=[User.from_api_response({"user": user}) for user in data["users"]],
68
+ users=[UserModel.from_api_response({"user": user}) for user in data["users"]],
73
69
  total=data["total"],
74
70
  has_more=data["has_more"],
75
71
  )
recallrai/session.py CHANGED
@@ -1,18 +1,21 @@
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
5
  from typing import List
9
- from .utils import HTTPClient, RecallrAIError
6
+ from .utils import HTTPClient
10
7
  from .models import (
11
8
  Context,
12
9
  Message,
13
10
  SessionStatus,
14
11
  MessageRole
15
12
  )
13
+ from .exceptions import (
14
+ UserNotFoundError,
15
+ SessionNotFoundError,
16
+ InvalidSessionStateError,
17
+ RecallrAIError
18
+ )
16
19
  from logging import getLogger
17
20
 
18
21
  logger = getLogger(__name__)
@@ -51,21 +54,16 @@ class Session:
51
54
  message: Content of the user message
52
55
 
53
56
  Raises:
54
- BadRequestError: If the session is already processed
55
- NotFoundError: If the session or user is not found
57
+ UserNotFoundError: If the user is not found
58
+ SessionNotFoundError: If the session is not found
59
+ InvalidSessionStateError: If the session is already processed or processing
60
+ AuthenticationError: If the API key or project ID is invalid
61
+ InternalServerError: If the server encounters an error
62
+ NetworkError: If there are network issues
63
+ TimeoutError: If the request times out
64
+ RecallrAIError: For other API-related errors
56
65
  """
57
- # Check the status of session
58
- status = self.get_status()
59
- if status == SessionStatus.PROCESSED:
60
- raise RecallrAIError("Cannot add message to a session that has already been processed")
61
- elif status == SessionStatus.PROCESSING:
62
- raise RecallrAIError("Cannot add message to a session that is currently being processed")
63
-
64
- # Add the user message
65
- self._http.post(
66
- f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/add-message",
67
- data={"message": message, "role": MessageRole.USER},
68
- )
66
+ self._add_message(message, MessageRole.USER)
69
67
 
70
68
  def add_assistant_message(self, message: str) -> None:
71
69
  """
@@ -75,21 +73,56 @@ class Session:
75
73
  message: Content of the assistant message
76
74
 
77
75
  Raises:
78
- BadRequestError: If the session is already processed
79
- NotFoundError: If the session or user is not found
76
+ UserNotFoundError: If the user is not found
77
+ SessionNotFoundError: If the session is not found
78
+ InvalidSessionStateError: If the session is already processed or processing
79
+ AuthenticationError: If the API key or project ID is invalid
80
+ InternalServerError: If the server encounters an error
81
+ NetworkError: If there are network issues
82
+ TimeoutError: If the request times out
83
+ RecallrAIError: For other API-related errors
80
84
  """
81
- # Check the status of session
82
- status = self.get_status()
83
- if status == SessionStatus.PROCESSED:
84
- raise RecallrAIError("Cannot add message to a session that has already been processed")
85
- elif status == SessionStatus.PROCESSING:
86
- raise RecallrAIError("Cannot add message to a session that is currently being processed")
85
+ self._add_message(message, MessageRole.ASSISTANT)
86
+
87
+ def _add_message(self, message: str, role: MessageRole) -> None:
88
+ """
89
+ Internal helper to add a message to the session.
87
90
 
88
- # Add the assistant message
89
- self._http.post(
91
+ Args:
92
+ message: Content of the message
93
+ role: Role of the message sender
94
+
95
+ Raises:
96
+ UserNotFoundError: If the user is not found
97
+ SessionNotFoundError: If the session is not found
98
+ InvalidSessionStateError: If the session is already processed or processing
99
+ AuthenticationError: If the API key or project ID is invalid
100
+ InternalServerError: If the server encounters an error
101
+ NetworkError: If there are network issues
102
+ TimeoutError: If the request times out
103
+ RecallrAIError: For other API-related errors
104
+ """
105
+ response = self._http.post(
90
106
  f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/add-message",
91
- data={"message": message, "role": MessageRole.ASSISTANT},
107
+ data={"message": message, "role": role.value},
92
108
  )
109
+
110
+ if response.status_code == 404:
111
+ # Check if it's a user not found or session not found error
112
+ detail = response.json().get('detail', '')
113
+ if f"User {self.user_id} not found" in detail:
114
+ raise UserNotFoundError(user_id=self.user_id)
115
+ else:
116
+ raise SessionNotFoundError(session_id=self.session_id)
117
+ elif response.status_code == 400:
118
+ raise InvalidSessionStateError(
119
+ message=f"Cannot add message to session with status {self.get_status()}",
120
+ )
121
+ elif response.status_code != 200:
122
+ raise RecallrAIError(
123
+ message=f"Failed to add message: {response.json().get('detail', 'Unknown error')}",
124
+ http_status=response.status_code
125
+ )
93
126
 
94
127
  def get_context(self) -> Context:
95
128
  """
@@ -102,17 +135,36 @@ class Session:
102
135
  Context information with the memory text and whether memory was used
103
136
 
104
137
  Raises:
105
- NotFoundError: If the session or user is not found
138
+ UserNotFoundError: If the user is not found
139
+ SessionNotFoundError: If the session is not found
140
+ AuthenticationError: If the API key or project ID is invalid
141
+ InternalServerError: If the server encounters an error
142
+ NetworkError: If there are network issues
143
+ TimeoutError: If the request times out
144
+ RecallrAIError: For other API-related errors
106
145
  """
107
- status = self.get_status()
108
- if status == SessionStatus.PROCESSED:
109
- logger.warning("Cannot add message to a session that has already been processed")
110
- elif status == SessionStatus.PROCESSING:
111
- logger.warning("Cannot add message to a session that is currently being processed")
112
146
  response = self._http.get(
113
147
  f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/context"
114
148
  )
115
- return Context.from_api_response(response)
149
+
150
+ if response.status_code == 404:
151
+ # Check if it's a user not found or session not found error
152
+ detail = response.json().get('detail', '')
153
+ if f"User {self.user_id} not found" in detail:
154
+ raise UserNotFoundError(user_id=self.user_id)
155
+ else:
156
+ raise SessionNotFoundError(session_id=self.session_id)
157
+ elif response.status_code != 200:
158
+ raise RecallrAIError(
159
+ message=f"Failed to get context: {response.json().get('detail', 'Unknown error')}",
160
+ http_status=response.status_code
161
+ )
162
+ status = self.get_status()
163
+ if status == SessionStatus.PROCESSED:
164
+ logger.warning("You are trying to get context for a processed session. Why do you need it?")
165
+ elif status == SessionStatus.PROCESSING:
166
+ logger.warning("You are trying to get context for a processing session. Why do you need it?")
167
+ return Context.from_api_response(response.json())
116
168
 
117
169
  def process(self) -> None:
118
170
  """
@@ -122,21 +174,35 @@ class Session:
122
174
  the user's memory.
123
175
 
124
176
  Raises:
125
- BadRequestError: If the session is already processed or being processed
126
- NotFoundError: If the session or user is not found
127
- SessionProcessingError: If there is an error during processing
177
+ UserNotFoundError: If the user is not found
178
+ SessionNotFoundError: If the session is not found
179
+ InvalidSessionStateError: If the session is already processed or being processed
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
128
185
  """
129
- # Check the status of session
130
- status = self.get_status()
131
- if status == SessionStatus.PROCESSED:
132
- raise RecallrAIError("Cannot process a session that has already been processed")
133
- elif status == SessionStatus.PROCESSING:
134
- raise RecallrAIError("Cannot process a session that is currently being processed")
135
-
136
- # Process the session
137
- self._http.post(
186
+ response = self._http.post(
138
187
  f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/process"
139
188
  )
189
+
190
+ if response.status_code == 404:
191
+ # Check if it's a user not found or session not found error
192
+ detail = response.json().get('detail', '')
193
+ if f"User {self.user_id} not found" in detail:
194
+ raise UserNotFoundError(user_id=self.user_id)
195
+ else:
196
+ raise SessionNotFoundError(session_id=self.session_id)
197
+ elif response.status_code == 400:
198
+ raise InvalidSessionStateError(
199
+ message=f"{response.json().get('detail', f'Cannot process session with status {self.get_status()}')}",
200
+ )
201
+ elif response.status_code != 200:
202
+ raise RecallrAIError(
203
+ message=f"Failed to process session: {response.json().get('detail', 'Unknown error')}",
204
+ http_status=response.status_code
205
+ )
140
206
 
141
207
  def get_status(self) -> SessionStatus:
142
208
  """
@@ -146,12 +212,32 @@ class Session:
146
212
  SessionStatus: The current status of the session
147
213
 
148
214
  Raises:
149
- NotFoundError: If the session or user is not found
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
150
222
  """
151
223
  response = self._http.get(
152
224
  f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/status"
153
225
  )
154
- return SessionStatus(response["status"])
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(user_id=self.user_id)
232
+ else:
233
+ raise SessionNotFoundError(session_id=self.session_id)
234
+ elif response.status_code != 200:
235
+ raise RecallrAIError(
236
+ message=f"Failed to get session status: {response.json().get('detail', 'Unknown error')}",
237
+ http_status=response.status_code
238
+ )
239
+
240
+ return SessionStatus(response.json()["status"])
155
241
 
156
242
  def get_messages(self) -> List[Message]:
157
243
  """
@@ -161,9 +247,30 @@ class Session:
161
247
  List of messages in the session
162
248
 
163
249
  Raises:
164
- NotFoundError: If the session or user is not found
250
+ UserNotFoundError: If the user is not found
251
+ SessionNotFoundError: If the session is not found
252
+ AuthenticationError: If the API key or project ID is invalid
253
+ InternalServerError: If the server encounters an error
254
+ NetworkError: If there are network issues
255
+ TimeoutError: If the request times out
256
+ RecallrAIError: For other API-related errors
165
257
  """
166
258
  response = self._http.get(
167
259
  f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/messages"
168
260
  )
169
- return [Message(**msg) for msg in response["messages"]]
261
+
262
+ if response.status_code == 404:
263
+ # Check if it's a user not found or session not found error
264
+ detail = response.json().get('detail', '')
265
+ if f"User {self.user_id} not found" in detail:
266
+ raise UserNotFoundError(user_id=self.user_id)
267
+ else:
268
+ raise SessionNotFoundError(session_id=self.session_id)
269
+ elif response.status_code != 200:
270
+ raise RecallrAIError(
271
+ message=f"Failed to get messages: {response.json().get('detail', 'Unknown error')}",
272
+ http_status=response.status_code
273
+ )
274
+
275
+ data = response.json()
276
+ return [Message(**msg) for msg in data["messages"]]
recallrai/user.py CHANGED
@@ -4,8 +4,17 @@ User management functionality for the RecallrAI SDK.
4
4
 
5
5
  from typing import Any, Dict, Optional
6
6
  from .utils import HTTPClient
7
- from .models import User as UserModel, SessionList
7
+ from .models import UserModel, SessionList
8
8
  from .session import Session
9
+ from .exceptions import (
10
+ UserNotFoundError,
11
+ UserAlreadyExistsError,
12
+ SessionNotFoundError,
13
+ RecallrAIError
14
+ )
15
+ from logging import getLogger
16
+
17
+ logger = getLogger(__name__)
9
18
 
10
19
  class User:
11
20
  """
@@ -46,18 +55,33 @@ class User:
46
55
  The updated user object
47
56
 
48
57
  Raises:
49
- NotFoundError: If the user is not found
50
- ValidationError: If the new_user_id is invalid
51
- BadRequestError: If a user with the new_user_id already exists
58
+ UserNotFoundError: If the user is not found
59
+ UserAlreadyExistsError: If a user with the new_user_id already exists
60
+ AuthenticationError: If the API key or project ID is invalid
61
+ InternalServerError: If the server encounters an error
62
+ NetworkError: If there are network issues
63
+ TimeoutError: If the request times out
64
+ RecallrAIError: For other API-related errors
52
65
  """
53
66
  data = {}
54
67
  if new_metadata is not None:
55
- data["new_metadata"] = new_metadata
68
+ data["metadata"] = new_metadata
56
69
  if new_user_id is not None:
57
70
  data["new_user_id"] = new_user_id
58
71
 
59
72
  response = self._http.put(f"/api/v1/users/{self.user_id}", data=data)
60
- updated_data = UserModel.from_api_response(response)
73
+
74
+ if response.status_code == 404:
75
+ raise UserNotFoundError(user_id=self.user_id)
76
+ elif response.status_code == 409:
77
+ raise UserAlreadyExistsError(user_id=new_user_id)
78
+ elif response.status_code != 200:
79
+ raise RecallrAIError(
80
+ message=f"Failed to update user: {response.json().get('detail', 'Unknown error')}",
81
+ http_status=response.status_code
82
+ )
83
+
84
+ updated_data = UserModel.from_api_response(response.json())
61
85
 
62
86
  # Update internal state
63
87
  self._user_data = updated_data
@@ -72,9 +96,22 @@ class User:
72
96
  Delete this user.
73
97
 
74
98
  Raises:
75
- NotFoundError: If the user is not found
99
+ UserNotFoundError: If the user is not found
100
+ AuthenticationError: If the API key or project ID is invalid
101
+ InternalServerError: If the server encounters an error
102
+ NetworkError: If there are network issues
103
+ TimeoutError: If the request times out
104
+ RecallrAIError: For other API-related errors
76
105
  """
77
- self._http.delete(f"/api/v1/users/{self.user_id}")
106
+ response = self._http.delete(f"/api/v1/users/{self.user_id}")
107
+
108
+ if response.status_code == 404:
109
+ raise UserNotFoundError(user_id=self.user_id)
110
+ elif response.status_code != 204:
111
+ raise RecallrAIError(
112
+ message=f"Failed to delete user: {response.json().get('detail', 'Unknown error')}",
113
+ http_status=response.status_code
114
+ )
78
115
 
79
116
  def create_session(self, auto_process_after_minutes: int = -1) -> Session:
80
117
  """
@@ -87,14 +124,27 @@ class User:
87
124
  A Session object to interact with the created session
88
125
 
89
126
  Raises:
90
- ValidationError: If auto_process_after_minutes is invalid
127
+ UserNotFoundError: If the user is not found
128
+ AuthenticationError: If the API key or project ID is invalid
129
+ InternalServerError: If the server encounters an error
130
+ NetworkError: If there are network issues
131
+ TimeoutError: If the request times out
132
+ RecallrAIError: For other API-related errors
91
133
  """
92
134
  response = self._http.post(
93
135
  f"/api/v1/users/{self.user_id}/sessions",
94
136
  data={"auto_process_after_minutes": auto_process_after_minutes},
95
137
  )
96
138
 
97
- session_id = response["session_id"]
139
+ if response.status_code == 404:
140
+ raise UserNotFoundError(user_id=self.user_id)
141
+ elif response.status_code != 201:
142
+ raise RecallrAIError(
143
+ message=f"Failed to create session: {response.json().get('detail', 'Unknown error')}",
144
+ http_status=response.status_code
145
+ )
146
+
147
+ session_id = response.json()["session_id"]
98
148
  return Session(self._http, self.user_id, session_id)
99
149
 
100
150
  def get_session(self, session_id: str) -> Session:
@@ -108,9 +158,23 @@ class User:
108
158
  A Session object to interact with the session
109
159
 
110
160
  Raises:
111
- NotFoundError: If the session is not found
161
+ UserNotFoundError: If the user is not found
162
+ SessionNotFoundError: If the session is not found
163
+ AuthenticationError: If the API key or project ID is invalid
164
+ InternalServerError: If the server encounters an error
165
+ NetworkError: If there are network issues
166
+ TimeoutError: If the request times out
167
+ RecallrAIError: For other API-related errors
112
168
  """
113
- return Session(self._http, self.user_id, session_id)
169
+ # Verify the session exists by checking its status
170
+ session = Session(self._http, self.user_id, session_id)
171
+ try:
172
+ session.get_status() # This will raise appropriate errors if the session doesn't exist
173
+ return session
174
+ except SessionNotFoundError:
175
+ raise
176
+ except Exception as e:
177
+ raise RecallrAIError(f"Error retrieving session: {str(e)}")
114
178
 
115
179
  def list_sessions(self, offset: int = 0, limit: int = 10) -> SessionList:
116
180
  """
@@ -122,9 +186,26 @@ class User:
122
186
 
123
187
  Returns:
124
188
  List of sessions with pagination info
189
+
190
+ Raises:
191
+ UserNotFoundError: If the user is not found
192
+ AuthenticationError: If the API key or project ID is invalid
193
+ InternalServerError: If the server encounters an error
194
+ NetworkError: If there are network issues
195
+ TimeoutError: If the request times out
196
+ RecallrAIError: For other API-related errors
125
197
  """
126
198
  response = self._http.get(
127
199
  f"/api/v1/users/{self.user_id}/sessions",
128
200
  params={"offset": offset, "limit": limit},
129
201
  )
130
- return SessionList.from_api_response(response)
202
+
203
+ if response.status_code == 404:
204
+ raise UserNotFoundError(user_id=self.user_id)
205
+ elif response.status_code != 200:
206
+ raise RecallrAIError(
207
+ message=f"Failed to list sessions: {response.json().get('detail', 'Unknown error')}",
208
+ http_status=response.status_code
209
+ )
210
+
211
+ return SessionList.from_api_response(response.json())
@@ -1,10 +1,8 @@
1
- # Path: recallrai/utils/__init__.py
2
- # Description: Package initialization for utilities
3
-
4
- from .http import HTTPClient
5
- from .exceptions import RecallrAIError
1
+ """
2
+ Utility functions for the SDK.
3
+ """
4
+ from .http_client import HTTPClient
6
5
 
7
6
  __all__ = [
8
7
  "HTTPClient",
9
- "RecallrAIError",
10
- ]
8
+ ]