recallrai 0.0.1__py3-none-any.whl → 0.1.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 CHANGED
@@ -0,0 +1,20 @@
1
+ # Path: recallrai/__init__.py
2
+ # Description: Package initialization file with SDK version and main class exports
3
+
4
+ """
5
+ RecallrAI Python SDK
6
+
7
+ This package provides a Python interface to interact with the RecallrAI API.
8
+ """
9
+
10
+ from .client import RecallrAI
11
+ from .user import User
12
+ from .session import Session
13
+
14
+ __version__ = "0.1.1"
15
+
16
+ __all__ = [
17
+ "RecallrAI",
18
+ "User",
19
+ "Session",
20
+ ]
recallrai/client.py ADDED
@@ -0,0 +1,135 @@
1
+ # Path: recallrai/client.py
2
+ # Description: Main client class for the RecallrAI SDK
3
+
4
+ """
5
+ Main client class for the RecallrAI SDK.
6
+
7
+ This module provides the RecallrAI class, which is the primary interface for the SDK.
8
+ """
9
+
10
+ from typing import Any, Dict, Optional
11
+ from .models import User as UserModel, UserList
12
+ from .user import User
13
+ from .utils import HTTPClient
14
+ from .exceptions import (
15
+ UserAlreadyExistsError,
16
+ UserNotFoundError,
17
+ RecallrAIError,
18
+ )
19
+ from logging import getLogger
20
+
21
+ logger = getLogger(__name__)
22
+
23
+ class RecallrAI:
24
+ """
25
+ Main client for interacting with the RecallrAI API.
26
+
27
+ This class provides methods for creating and managing users, sessions, and memories.
28
+ """
29
+
30
+ def __init__(
31
+ self,
32
+ api_key: str,
33
+ project_id: str,
34
+ base_url: str = "https://api.recallrai.com",
35
+ timeout: int = 30,
36
+ ):
37
+ """
38
+ Initialize the RecallrAI client.
39
+
40
+ Args:
41
+ api_key: Your RecallrAI API key
42
+ project_id: Your project ID
43
+ base_url: The base URL for the RecallrAI API
44
+ timeout: Request timeout in seconds
45
+ """
46
+ if not api_key.startswith("rai_"):
47
+ raise ValueError("API key must start with 'rai_'")
48
+
49
+ self.api_key = api_key
50
+ self.project_id = project_id
51
+ self.base_url = base_url
52
+
53
+ self.http = HTTPClient(
54
+ api_key=self.api_key,
55
+ project_id=self.project_id,
56
+ base_url=self.base_url,
57
+ timeout=timeout,
58
+ )
59
+
60
+ # User management
61
+ def create_user(self, user_id: str, metadata: Optional[Dict[str, Any]] = None) -> User:
62
+ """
63
+ Create a new user.
64
+
65
+ Args:
66
+ user_id: Unique identifier for the user
67
+ metadata: Optional metadata to associate with the user
68
+
69
+ Returns:
70
+ The created user object
71
+
72
+ Raises:
73
+ UserAlreadyExistsError: If a user with the same ID already exists
74
+ AuthenticationError: If the API key or project ID is invalid
75
+ InternalServerError: If the server encounters an error
76
+ NetworkError: If there are network issues
77
+ TimeoutError: If the request times out
78
+ RecallrAIError: For other API-related errors
79
+ """
80
+ response = self.http.post("/api/v1/users", data={"user_id": user_id, "metadata": metadata or {}})
81
+ if response.status_code == 409:
82
+ raise UserAlreadyExistsError(user_id=user_id)
83
+ elif response.status_code != 201:
84
+ raise RecallrAIError("Failed to create user", http_status=response.status_code)
85
+ user_data = UserModel.from_api_response(response.json())
86
+ return User(self.http, user_data)
87
+
88
+ def get_user(self, user_id: str) -> User:
89
+ """
90
+ Get a user by ID.
91
+
92
+ Args:
93
+ user_id: Unique identifier of the user
94
+
95
+ Returns:
96
+ A User object representing the user
97
+
98
+ Raises:
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
105
+ """
106
+ response = self.http.get(f"/api/v1/users/{user_id}")
107
+ if response.status_code == 404:
108
+ raise UserNotFoundError(user_id=user_id)
109
+ elif response.status_code != 200:
110
+ raise RecallrAIError("Failed to retrieve user", http_status=response.status_code)
111
+ user_data = UserModel.from_api_response(response.json())
112
+ return User(self.http, user_data)
113
+
114
+ def list_users(self, offset: int = 0, limit: int = 10) -> UserList:
115
+ """
116
+ List users with pagination.
117
+
118
+ Args:
119
+ offset: Number of records to skip
120
+ limit: Maximum number of records to return
121
+
122
+ Returns:
123
+ List of users with pagination info
124
+
125
+ Raises:
126
+ AuthenticationError: If the API key or project ID is invalid
127
+ InternalServerError: If the server encounters an error
128
+ NetworkError: If there are network issues
129
+ TimeoutError: If the request times out
130
+ RecallrAIError: For other API-related errors
131
+ """
132
+ response = self.http.get("/api/v1/users", params={"offset": offset, "limit": limit})
133
+ if response.status_code != 200:
134
+ raise RecallrAIError("Failed to list users", http_status=response.status_code)
135
+ return UserList.from_api_response(response.json())
@@ -0,0 +1,28 @@
1
+ """
2
+ Exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from .auth import AuthenticationError
6
+ from .base import RecallrAIError
7
+ from .network import NetworkError, TimeoutError, ConnectionError
8
+ from .server import ServerError, InternalServerError
9
+ from .sessions import SessionError, SessionNotFoundError, InvalidSessionStateError
10
+ from .users import UserError, UserNotFoundError, UserAlreadyExistsError
11
+ from .validation import ValidationError
12
+
13
+ __all__ = [
14
+ "RecallrAIError",
15
+ "AuthenticationError",
16
+ "NetworkError",
17
+ "TimeoutError",
18
+ "ConnectionError",
19
+ "ServerError",
20
+ "InternalServerError",
21
+ "SessionError",
22
+ "SessionNotFoundError",
23
+ "InvalidSessionStateError",
24
+ "UserError",
25
+ "UserNotFoundError",
26
+ "UserAlreadyExistsError",
27
+ "ValidationError",
28
+ ]
@@ -0,0 +1,24 @@
1
+ """
2
+ Authentication-related exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+ from .base import RecallrAIError
7
+
8
+
9
+ class AuthenticationError(RecallrAIError):
10
+ """
11
+ Raised when there is an authentication issue with the API key.
12
+
13
+ This exception is typically raised when the API key is invalid,
14
+ has been revoked, or doesn't have the necessary permissions.
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ message: str = "Invalid API key or authentication failed",
20
+ code: str = "authentication_error",
21
+ http_status: int = 401,
22
+ details: Optional[Dict[str, Any]] = None
23
+ ):
24
+ super().__init__(message, code, http_status, details)
@@ -0,0 +1,37 @@
1
+ """
2
+ Base exception classes for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+
7
+
8
+ class RecallrAIError(Exception):
9
+ """Base exception for all RecallrAI SDK errors."""
10
+
11
+ def __init__(
12
+ self,
13
+ message: str,
14
+ code: Optional[str] = None,
15
+ http_status: Optional[int] = None,
16
+ details: Optional[Dict[str, Any]] = None
17
+ ):
18
+ """
19
+ Initialize a RecallrAI error.
20
+
21
+ Args:
22
+ message: A human-readable error message
23
+ code: An optional error code
24
+ http_status: The HTTP status code that triggered this error
25
+ details: Optional additional details about the error
26
+ """
27
+ self.message = message
28
+ self.code = code
29
+ self.http_status = http_status
30
+ self.details = details or {}
31
+ super().__init__(self.message)
32
+
33
+ def __str__(self) -> str:
34
+ """Return a string representation of the error."""
35
+ if self.code:
36
+ return f"{self.code}: {self.message}"
37
+ return self.message
@@ -0,0 +1,58 @@
1
+ """
2
+ Network-related exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+ from .base import RecallrAIError
7
+
8
+
9
+ class NetworkError(RecallrAIError):
10
+ """
11
+ Base class for network-related exceptions.
12
+
13
+ This exception is raised for errors related to network connectivity
14
+ and communication with the RecallrAI API.
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ message: str = "Network error occurred",
20
+ code: str = "network_error",
21
+ http_status: Optional[int] = None,
22
+ details: Optional[Dict[str, Any]] = None
23
+ ):
24
+ super().__init__(message, code, http_status, details)
25
+
26
+
27
+ class TimeoutError(NetworkError):
28
+ """
29
+ Raised when a request times out.
30
+
31
+ This exception is raised when a request to the RecallrAI API
32
+ takes longer than the configured timeout.
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ message: str = "Request timed out",
38
+ code: str = "timeout",
39
+ details: Optional[Dict[str, Any]] = None
40
+ ):
41
+ super().__init__(message, code, None, details)
42
+
43
+
44
+ class ConnectionError(NetworkError):
45
+ """
46
+ Raised when a connection error occurs.
47
+
48
+ This exception is raised when there's an issue connecting to
49
+ the RecallrAI API, such as DNS resolution issues or network unavailability.
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ message: str = "Failed to connect to the RecallrAI API",
55
+ code: str = "connection_error",
56
+ details: Optional[Dict[str, Any]] = None
57
+ ):
58
+ super().__init__(message, code, None, details)
@@ -0,0 +1,82 @@
1
+ """
2
+ Server-related exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+ from .base import RecallrAIError
7
+
8
+
9
+ class ServerError(RecallrAIError):
10
+ """
11
+ Base class for server-related exceptions.
12
+ """
13
+ def __init__(
14
+ self,
15
+ message: str = "Server error occurred",
16
+ code: str = "server_error",
17
+ http_status: int = 500,
18
+ details: Optional[Dict[str, Any]] = None
19
+ ):
20
+ super().__init__(message, code, http_status, details)
21
+
22
+ class InternalServerError(ServerError):
23
+ """
24
+ Raised when the RecallrAI API encounters an internal server error.
25
+
26
+ This exception is typically raised when the API returns a 5xx error code.
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ message: str = "Internal server error",
32
+ code: str = "server_error",
33
+ http_status: int = 500,
34
+ details: Optional[Dict[str, Any]] = None
35
+ ):
36
+ super().__init__(message, code, http_status, details)
37
+
38
+
39
+ # class RateLimitError(ServerError):
40
+ # """
41
+ # Raised when the API rate limit has been exceeded.
42
+ #
43
+ # This exception is raised when too many requests are made in a
44
+ # short period of time.
45
+ # """
46
+
47
+ # def __init__(
48
+ # self,
49
+ # message: str = "API rate limit exceeded",
50
+ # code: str = "rate_limit_exceeded",
51
+ # http_status: int = 429,
52
+ # retry_after: Optional[int] = None,
53
+ # details: Optional[Dict[str, Any]] = None
54
+ # ):
55
+ # details = details or {}
56
+ # if retry_after:
57
+ # details["retry_after"] = retry_after
58
+ # super().__init__(message, code, http_status, details)
59
+ # self.retry_after = retry_after
60
+
61
+
62
+ # class ServiceUnavailableError(ServerError):
63
+ # """
64
+ # Raised when the RecallrAI service is temporarily unavailable.
65
+ #
66
+ # This exception is raised when the API is down for maintenance
67
+ # or experiencing issues.
68
+ # """
69
+
70
+ # def __init__(
71
+ # self,
72
+ # message: str = "Service temporarily unavailable",
73
+ # code: str = "service_unavailable",
74
+ # http_status: int = 503,
75
+ # retry_after: Optional[int] = None,
76
+ # details: Optional[Dict[str, Any]] = None
77
+ # ):
78
+ # details = details or {}
79
+ # if retry_after:
80
+ # details["retry_after"] = retry_after
81
+ # super().__init__(message, code, http_status, details)
82
+ # self.retry_after = retry_after
@@ -0,0 +1,60 @@
1
+ """
2
+ Sessions-related exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+ from .base import RecallrAIError
7
+
8
+ class SessionError(RecallrAIError):
9
+ """
10
+ Base class for session-related exceptions.
11
+
12
+ This exception is raised for errors related to session management
13
+ in the RecallrAI API.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ message: str = "Session error occurred",
19
+ code: str = "session_error",
20
+ http_status: Optional[int] = None,
21
+ details: Optional[Dict[str, Any]] = None
22
+ ):
23
+ super().__init__(message, code, http_status, details)
24
+
25
+ class InvalidSessionStateError(SessionError):
26
+ """
27
+ Raised when a session is in an invalid state.
28
+
29
+ This exception is typically raised when trying to perform an action
30
+ on a session that is not in the expected state.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ message: str = "Invalid session state",
36
+ code: str = "invalid_session_state",
37
+ http_status: int = 400,
38
+ details: Optional[Dict[str, Any]] = None
39
+ ):
40
+ super().__init__(message, code, http_status, details)
41
+
42
+ class SessionNotFoundError(SessionError):
43
+ """
44
+ Raised when a session is not found.
45
+
46
+ This exception is typically raised when trying to access or modify
47
+ a session that doesn't exist.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ session_id: Optional[str] = None,
53
+ message: Optional[str] = None,
54
+ code: str = "session_not_found",
55
+ http_status: int = 404,
56
+ details: Optional[Dict[str, Any]] = None
57
+ ):
58
+ message = message or f"Session{f' {session_id}' if session_id else ''} not found"
59
+ super().__init__(message, code, http_status, details)
60
+ self.session_id = session_id
@@ -0,0 +1,61 @@
1
+ """
2
+ Users-related exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+ from .base import RecallrAIError
7
+
8
+ class UserError(RecallrAIError):
9
+ """
10
+ Base class for user-related exceptions.
11
+
12
+ This exception is raised for errors related to user management
13
+ in the RecallrAI API.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ message: str = "User error occurred",
19
+ code: str = "user_error",
20
+ http_status: Optional[int] = None,
21
+ details: Optional[Dict[str, Any]] = None
22
+ ):
23
+ super().__init__(message, code, http_status, details)
24
+
25
+ class UserNotFoundError(UserError):
26
+ """
27
+ Raised when a user is not found.
28
+
29
+ This exception is typically raised when trying to access or modify
30
+ a user that doesn't exist.
31
+ """
32
+ def __init__(
33
+ self,
34
+ user_id: Optional[str] = None,
35
+ message: Optional[str] = None,
36
+ code: str = "user_not_found",
37
+ http_status: int = 404,
38
+ details: Optional[Dict[str, Any]] = None
39
+ ):
40
+ message = message or f"User{f' {user_id}' if user_id else ''} not found"
41
+ super().__init__(message, code, http_status, details)
42
+ self.user_id = user_id
43
+
44
+ class UserAlreadyExistsError(UserError):
45
+ """
46
+ Raised when a user already exists.
47
+
48
+ This exception is typically raised when trying to create a user
49
+ that already exists in the system.
50
+ """
51
+ def __init__(
52
+ self,
53
+ user_id: Optional[str] = None,
54
+ message: Optional[str] = None,
55
+ code: str = "user_already_exists",
56
+ http_status: int = 409,
57
+ details: Optional[Dict[str, Any]] = None
58
+ ):
59
+ message = message or f"User{f' {user_id}' if user_id else ''} already exists"
60
+ super().__init__(message, code, http_status, details)
61
+ self.user_id = user_id
@@ -0,0 +1,24 @@
1
+ """
2
+ Validation-related exceptions for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional, Union
6
+ from .base import RecallrAIError
7
+
8
+
9
+ class ValidationError(RecallrAIError):
10
+ """
11
+ Raised when request parameters fail validation.
12
+
13
+ This exception is raised when the API rejects a request
14
+ due to invalid or missing parameters.
15
+ """
16
+
17
+ def __init__(
18
+ self,
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)
@@ -0,0 +1,16 @@
1
+ # Path: recallrai/models/__init__.py
2
+ # Description: Package initialization for data models
3
+
4
+ from .session import Context, Message, MessageRole, Session, SessionList, SessionStatus
5
+ from .user import User, UserList
6
+
7
+ __all__ = [
8
+ "User",
9
+ "UserList",
10
+ "Session",
11
+ "SessionList",
12
+ "SessionStatus",
13
+ "Message",
14
+ "MessageRole",
15
+ "Context",
16
+ ]
@@ -0,0 +1,138 @@
1
+ # Path: recallrai/models/session.py
2
+ # Description: Session data models for the RecallrAI SDK
3
+
4
+ """
5
+ Session-related data models for the RecallrAI SDK.
6
+ """
7
+
8
+ import enum, uuid
9
+ from datetime import datetime
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ from pydantic import BaseModel, Field
13
+
14
+
15
+ class MessageRole(str, enum.Enum):
16
+ """
17
+ Message role in a conversation.
18
+ """
19
+ USER = "user"
20
+ ASSISTANT = "assistant"
21
+
22
+
23
+ class Message(BaseModel):
24
+ """
25
+ Represents a message in a conversation session.
26
+ """
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")
30
+
31
+ class Config:
32
+ """Pydantic configuration."""
33
+ frozen = True
34
+ json_encoders = {
35
+ datetime: lambda dt: dt.isoformat()
36
+ }
37
+
38
+
39
+ class SessionStatus(str, enum.Enum):
40
+ """
41
+ Status of a session.
42
+ """
43
+ PENDING = "pending"
44
+ PROCESSING = "processing"
45
+ PROCESSED = "processed"
46
+
47
+
48
+ class Session(BaseModel):
49
+ """
50
+ Represents a conversation session.
51
+ """
52
+ session_id: uuid.UUID = Field(..., description="Unique identifier for the session")
53
+ status: SessionStatus = Field(..., description="Current status of the session")
54
+ created_at: datetime = Field(..., description="When the session was created")
55
+
56
+ class Config:
57
+ """Pydantic configuration."""
58
+ frozen = True
59
+ json_encoders = {
60
+ datetime: lambda dt: dt.isoformat(),
61
+ uuid.UUID: lambda id: str(id)
62
+ }
63
+
64
+ @classmethod
65
+ def from_api_response(cls, data: Dict[str, Any]) -> "Session":
66
+ """
67
+ Create a Session instance from an API response.
68
+
69
+ Args:
70
+ data: API response data
71
+
72
+ Returns:
73
+ A Session instance
74
+ """
75
+ return cls(
76
+ session_id=data["session_id"],
77
+ status=data.get("status", SessionStatus.PENDING),
78
+ created_at=data.get("created_at", datetime.now()),
79
+ messages=None
80
+ )
81
+
82
+
83
+ class SessionList(BaseModel):
84
+ """
85
+ Represents a paginated list of sessions.
86
+ """
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")
90
+
91
+ class Config:
92
+ """Pydantic configuration."""
93
+ frozen = True
94
+
95
+ @classmethod
96
+ def from_api_response(cls, data: Dict[str, Any]) -> "SessionList":
97
+ """
98
+ Create a SessionList instance from an API response.
99
+
100
+ Args:
101
+ data: API response data
102
+
103
+ Returns:
104
+ A SessionList instance
105
+ """
106
+ return cls(
107
+ sessions=[Session.from_api_response(session) for session in data["sessions"]],
108
+ total=data["total"],
109
+ has_more=data["has_more"],
110
+ )
111
+
112
+
113
+ class Context(BaseModel):
114
+ """
115
+ Represents the context for a session.
116
+ """
117
+ memory_used: bool = Field(..., description="Whether memory was used to generate the context")
118
+ context: str = Field(..., description="The context for the session")
119
+
120
+ class Config:
121
+ """Pydantic configuration."""
122
+ frozen = True
123
+
124
+ @classmethod
125
+ def from_api_response(cls, data: Dict[str, Any]) -> "Context":
126
+ """
127
+ Create a Context instance from an API response.
128
+
129
+ Args:
130
+ data: API response data
131
+
132
+ Returns:
133
+ A Context instance
134
+ """
135
+ return cls(
136
+ memory_used=data["memory_used"],
137
+ context=data["context"],
138
+ )