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.

@@ -0,0 +1,75 @@
1
+ # Path: recallrai/models/user.py
2
+ # Description: User data models for the RecallrAI SDK
3
+
4
+ """
5
+ User-related data models for the RecallrAI SDK.
6
+ """
7
+
8
+ from datetime import datetime
9
+ from typing import Any, Dict
10
+
11
+ from pydantic import BaseModel, Field
12
+
13
+
14
+ class User(BaseModel):
15
+ """Represents a user in the RecallrAI system."""
16
+
17
+ user_id: str = Field(..., description="Unique identifier for the user")
18
+ metadata: Dict[str, Any] = Field(default_factory=dict, description="Custom metadata for the user")
19
+ created_at: datetime = Field(..., description="When the user was created")
20
+ last_active_at: datetime = Field(..., description="When the user was last active")
21
+
22
+ class Config:
23
+ """Pydantic configuration."""
24
+ frozen = True
25
+ json_encoders = {
26
+ datetime: lambda dt: dt.isoformat()
27
+ }
28
+
29
+ @classmethod
30
+ def from_api_response(cls, data: Dict[str, Any]) -> "User":
31
+ """
32
+ Create a User instance from an API response.
33
+
34
+ Args:
35
+ data: API response data
36
+
37
+ Returns:
38
+ A User instance
39
+ """
40
+ if "user" in data:
41
+ user_data = data["user"]
42
+ else:
43
+ user_data = data
44
+
45
+ return cls(
46
+ user_id=user_data["user_id"],
47
+ metadata=user_data.get("metadata", {}),
48
+ created_at=user_data["created_at"],
49
+ last_active_at=user_data["last_active_at"],
50
+ )
51
+
52
+
53
+ class UserList(BaseModel):
54
+ """Represents a paginated list of users."""
55
+
56
+ users: list[User] = Field(..., description="List of users")
57
+ total: int = Field(..., description="Total number of users")
58
+ has_more: bool = Field(..., description="Whether there are more users to fetch")
59
+
60
+ @classmethod
61
+ def from_api_response(cls, data: Dict[str, Any]) -> "UserList":
62
+ """
63
+ Create a UserList instance from an API response.
64
+
65
+ Args:
66
+ data: API response data
67
+
68
+ Returns:
69
+ A UserList instance
70
+ """
71
+ return cls(
72
+ users=[User.from_api_response({"user": user}) for user in data["users"]],
73
+ total=data["total"],
74
+ has_more=data["has_more"],
75
+ )
recallrai/session.py ADDED
@@ -0,0 +1,279 @@
1
+ # Path: recallrai/session.py
2
+ # Description: Session management class for the RecallrAI SDK
3
+
4
+ """
5
+ Session management functionality for the RecallrAI SDK.
6
+ """
7
+
8
+ from typing import List
9
+ from .utils import HTTPClient
10
+ from .models import (
11
+ Context,
12
+ Message,
13
+ SessionStatus,
14
+ MessageRole
15
+ )
16
+ from .exceptions import (
17
+ UserNotFoundError,
18
+ SessionNotFoundError,
19
+ InvalidSessionStateError,
20
+ RecallrAIError
21
+ )
22
+ from logging import getLogger
23
+
24
+ logger = getLogger(__name__)
25
+
26
+ class Session:
27
+ """
28
+ Manages a conversation session with RecallrAI.
29
+
30
+ This class handles adding messages, retrieving context, and processing the session
31
+ to update the user's memory.
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ http_client: HTTPClient,
37
+ user_id: str,
38
+ session_id: str,
39
+ ):
40
+ """
41
+ Initialize a session.
42
+
43
+ Args:
44
+ http_client: HTTP client for API communication
45
+ user_id: ID of the user who owns this session
46
+ session_id: Unique identifier for the session
47
+ """
48
+ self._http = http_client
49
+ self.user_id = user_id
50
+ self.session_id = session_id
51
+
52
+ def add_user_message(self, message: str) -> None:
53
+ """
54
+ Add a user message to the session.
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.
74
+
75
+ Args:
76
+ message: Content of the assistant message
77
+
78
+ 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
107
+ """
108
+ response = self._http.post(
109
+ f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/add-message",
110
+ data={"message": message, "role": role.value},
111
+ )
112
+
113
+ if response.status_code == 404:
114
+ # Check if it's a user not found or session not found error
115
+ detail = response.json().get('detail', '')
116
+ if f"User {self.user_id} not found" in detail:
117
+ raise UserNotFoundError(user_id=self.user_id)
118
+ else:
119
+ raise SessionNotFoundError(session_id=self.session_id)
120
+ elif response.status_code == 400:
121
+ raise InvalidSessionStateError(
122
+ message=f"Cannot add message to session with status {self.get_status()}",
123
+ )
124
+ elif response.status_code != 200:
125
+ raise RecallrAIError(
126
+ message=f"Failed to add message: {response.json().get('detail', 'Unknown error')}",
127
+ http_status=response.status_code
128
+ )
129
+
130
+ def get_context(self) -> Context:
131
+ """
132
+ Get the current context for this session.
133
+
134
+ The context contains information from the user's memory that is relevant
135
+ to the current conversation.
136
+
137
+ Returns:
138
+ Context information with the memory text and whether memory was used
139
+
140
+ 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
148
+ """
149
+ response = self._http.get(
150
+ f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/context"
151
+ )
152
+
153
+ if response.status_code == 404:
154
+ # Check if it's a user not found or session not found error
155
+ detail = response.json().get('detail', '')
156
+ if f"User {self.user_id} not found" in detail:
157
+ raise UserNotFoundError(user_id=self.user_id)
158
+ else:
159
+ raise SessionNotFoundError(session_id=self.session_id)
160
+ elif response.status_code != 200:
161
+ raise RecallrAIError(
162
+ message=f"Failed to get context: {response.json().get('detail', 'Unknown error')}",
163
+ http_status=response.status_code
164
+ )
165
+ status = self.get_status()
166
+ if status == SessionStatus.PROCESSED:
167
+ logger.warning("Cannot add message to a session that has already been processed")
168
+ elif status == SessionStatus.PROCESSING:
169
+ logger.warning("Cannot add message to a session that is currently being processed")
170
+ return Context.from_api_response(response.json())
171
+
172
+ def process(self) -> None:
173
+ """
174
+ Process the session to update the user's memory.
175
+
176
+ This method triggers the processing of the conversation to extract and update
177
+ the user's memory.
178
+
179
+ Raises:
180
+ UserNotFoundError: If the user is not found
181
+ SessionNotFoundError: If the session is not found
182
+ InvalidSessionStateError: If the session is already processed or being processed
183
+ AuthenticationError: If the API key or project ID is invalid
184
+ InternalServerError: If the server encounters an error
185
+ NetworkError: If there are network issues
186
+ TimeoutError: If the request times out
187
+ RecallrAIError: For other API-related errors
188
+ """
189
+ response = self._http.post(
190
+ f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/process"
191
+ )
192
+
193
+ if response.status_code == 404:
194
+ # Check if it's a user not found or session not found error
195
+ detail = response.json().get('detail', '')
196
+ if f"User {self.user_id} not found" in detail:
197
+ raise UserNotFoundError(user_id=self.user_id)
198
+ else:
199
+ raise SessionNotFoundError(session_id=self.session_id)
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
+ )
204
+ elif response.status_code != 200:
205
+ raise RecallrAIError(
206
+ message=f"Failed to process session: {response.json().get('detail', 'Unknown error')}",
207
+ http_status=response.status_code
208
+ )
209
+
210
+ def get_status(self) -> SessionStatus:
211
+ """
212
+ Get the current status of the session.
213
+
214
+ Returns:
215
+ SessionStatus: The current status of the session
216
+
217
+ 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
225
+ """
226
+ response = self._http.get(
227
+ f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/status"
228
+ )
229
+
230
+ if response.status_code == 404:
231
+ # Check if it's a user not found or session not found error
232
+ detail = response.json().get('detail', '')
233
+ if f"User {self.user_id} not found" in detail:
234
+ raise UserNotFoundError(user_id=self.user_id)
235
+ else:
236
+ raise SessionNotFoundError(session_id=self.session_id)
237
+ elif response.status_code != 200:
238
+ raise RecallrAIError(
239
+ message=f"Failed to get session status: {response.json().get('detail', 'Unknown error')}",
240
+ http_status=response.status_code
241
+ )
242
+
243
+ return SessionStatus(response.json()["status"])
244
+
245
+ def get_messages(self) -> List[Message]:
246
+ """
247
+ Get all messages in the session.
248
+
249
+ Returns:
250
+ List of messages in the session
251
+
252
+ 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
260
+ """
261
+ response = self._http.get(
262
+ f"/api/v1/users/{self.user_id}/sessions/{self.session_id}/messages"
263
+ )
264
+
265
+ if response.status_code == 404:
266
+ # Check if it's a user not found or session not found error
267
+ detail = response.json().get('detail', '')
268
+ if f"User {self.user_id} not found" in detail:
269
+ raise UserNotFoundError(user_id=self.user_id)
270
+ else:
271
+ raise SessionNotFoundError(session_id=self.session_id)
272
+ elif response.status_code != 200:
273
+ raise RecallrAIError(
274
+ message=f"Failed to get messages: {response.json().get('detail', 'Unknown error')}",
275
+ http_status=response.status_code
276
+ )
277
+
278
+ data = response.json()
279
+ return [Message(**msg) for msg in data["messages"]]
recallrai/user.py ADDED
@@ -0,0 +1,211 @@
1
+ """
2
+ User management functionality for the RecallrAI SDK.
3
+ """
4
+
5
+ from typing import Any, Dict, Optional
6
+ from .utils import HTTPClient
7
+ from .models import User as UserModel, SessionList
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__)
18
+
19
+ class User:
20
+ """
21
+ Represents a user in the RecallrAI system with methods for user management.
22
+
23
+ This class wraps a user object and provides methods for updating user data,
24
+ and for creating and managing sessions.
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ http_client: HTTPClient,
30
+ user_data: UserModel,
31
+ ):
32
+ """
33
+ Initialize a user.
34
+
35
+ Args:
36
+ http_client: HTTP client for API communication
37
+ user_data: User data model with user information
38
+ """
39
+ self._http = http_client
40
+ self._user_data = user_data
41
+ self.user_id = user_data.user_id
42
+ self.metadata = user_data.metadata
43
+ self.created_at = user_data.created_at
44
+ self.last_active_at = user_data.last_active_at
45
+
46
+ def update(self, new_metadata: Optional[Dict[str, Any]] = None, new_user_id: Optional[str] = None) -> 'User':
47
+ """
48
+ Update this user's metadata or ID.
49
+
50
+ Args:
51
+ new_metadata: New metadata to associate with the user
52
+ new_user_id: New ID for the user
53
+
54
+ Returns:
55
+ The updated user object
56
+
57
+ Raises:
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
65
+ """
66
+ data = {}
67
+ if new_metadata is not None:
68
+ data["metadata"] = new_metadata
69
+ if new_user_id is not None:
70
+ data["new_user_id"] = new_user_id
71
+
72
+ response = self._http.put(f"/api/v1/users/{self.user_id}", data=data)
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())
85
+
86
+ # Update internal state
87
+ self._user_data = updated_data
88
+ self.user_id = updated_data.user_id
89
+ self.metadata = updated_data.metadata
90
+ self.last_active_at = updated_data.last_active_at
91
+
92
+ return self
93
+
94
+ def delete(self) -> None:
95
+ """
96
+ Delete this 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.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
+ )
115
+
116
+ def create_session(self, auto_process_after_minutes: int = -1) -> Session:
117
+ """
118
+ Create a new session for this user.
119
+
120
+ Args:
121
+ auto_process_after_minutes: Minutes to wait before auto-processing (-1 to disable)
122
+
123
+ Returns:
124
+ A Session object to interact with the created session
125
+
126
+ Raises:
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
133
+ """
134
+ response = self._http.post(
135
+ f"/api/v1/users/{self.user_id}/sessions",
136
+ data={"auto_process_after_minutes": auto_process_after_minutes},
137
+ )
138
+
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"]
148
+ return Session(self._http, self.user_id, session_id)
149
+
150
+ def get_session(self, session_id: str) -> Session:
151
+ """
152
+ Get an existing session for this user.
153
+
154
+ Args:
155
+ session_id: ID of the session to retrieve
156
+
157
+ Returns:
158
+ A Session object to interact with the session
159
+
160
+ Raises:
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
168
+ """
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)}")
178
+
179
+ def list_sessions(self, offset: int = 0, limit: int = 10) -> SessionList:
180
+ """
181
+ List sessions for this user with pagination.
182
+
183
+ Args:
184
+ offset: Number of records to skip
185
+ limit: Maximum number of records to return
186
+
187
+ Returns:
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
197
+ """
198
+ response = self._http.get(
199
+ f"/api/v1/users/{self.user_id}/sessions",
200
+ params={"offset": offset, "limit": limit},
201
+ )
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())
@@ -0,0 +1,8 @@
1
+ # Path: recallrai/utils/__init__.py
2
+ # Description: Package initialization for utilities
3
+
4
+ from .http_client import HTTPClient
5
+
6
+ __all__ = [
7
+ "HTTPClient",
8
+ ]
@@ -0,0 +1,123 @@
1
+ # Path: recallrai/utils/http.py
2
+ # Description: HTTP client utilities for the RecallrAI SDK
3
+
4
+ from httpx import Response, Client, TimeoutException, NetworkError, ConnectError
5
+ from typing import Any, Dict, Optional
6
+ from ..exceptions import (
7
+ TimeoutError,
8
+ NetworkError as CustomNetworkError,
9
+ ConnectionError,
10
+ ValidationError,
11
+ InternalServerError,
12
+ AuthenticationError,
13
+ )
14
+
15
+ class HTTPClient:
16
+ """HTTP client for making requests to the RecallrAI API."""
17
+
18
+ def __init__(
19
+ self,
20
+ api_key: str,
21
+ project_id: str,
22
+ base_url: str,
23
+ timeout: int = 30,
24
+ ):
25
+ """
26
+ Initialize the HTTP client.
27
+
28
+ Args:
29
+ api_key: Your RecallrAI API key
30
+ project_id: Your project ID
31
+ base_url: The base URL for the RecallrAI API
32
+ timeout: Request timeout in seconds
33
+ """
34
+ self.api_key = api_key
35
+ self.project_id = project_id
36
+ self.base_url = base_url.rstrip("/")
37
+ self.timeout = timeout
38
+ self.client = Client(
39
+ timeout=self.timeout,
40
+ headers={
41
+ "X-Api-Key": self.api_key,
42
+ "X-Project-Id": self.project_id,
43
+ "Content-Type": "application/json",
44
+ "Accept": "application/json",
45
+ "User-Agent": "RecallrAI-Python-SDK",
46
+ # TODO: "SDK-Version": "0.1.0",
47
+ },
48
+ )
49
+
50
+ def request(
51
+ self,
52
+ method: str,
53
+ path: str,
54
+ params: Optional[Dict[str, Any]] = None,
55
+ data: Optional[Dict[str, Any]] = None,
56
+ ) -> Response:
57
+ """
58
+ Make a request to the RecallrAI API.
59
+
60
+ Args:
61
+ method: HTTP method (GET, POST, PUT, DELETE)
62
+ path: API endpoint path
63
+ params: Query parameters
64
+ data: Request body data
65
+
66
+ Returns:
67
+ The parsed JSON response
68
+ """
69
+ url = f"{self.base_url}{path}"
70
+
71
+ # Filter out None values in params and data
72
+ if params:
73
+ params = {k: v for k, v in params.items() if v is not None}
74
+
75
+ if data:
76
+ data = {k: v for k, v in data.items() if v is not None}
77
+
78
+ try:
79
+ response = self.client.request(
80
+ method=method,
81
+ url=url,
82
+ params=params,
83
+ json=data,
84
+ )
85
+ if response.status_code == 422:
86
+ raise ValidationError(
87
+ details=response.json()["detail"],
88
+ )
89
+ elif response.status_code == 500:
90
+ raise InternalServerError(
91
+ details=response.json()["detail"],
92
+ )
93
+ elif response.status_code == 401:
94
+ raise AuthenticationError(
95
+ details=response.json()["detail"],
96
+ )
97
+
98
+ return response
99
+ except TimeoutException as e:
100
+ raise TimeoutError(f"Request timed out: {e}")
101
+ except NetworkError as e:
102
+ raise CustomNetworkError(f"Network error occurred: {e}")
103
+ except ConnectError as e:
104
+ raise ConnectionError(f"Failed to connect to the API: {e}")
105
+ except Exception as e:
106
+ # Handle other exceptions as needed
107
+ raise e
108
+
109
+ def get(self, path: str, params: Optional[Dict[str, Any]] = None) -> Response:
110
+ """Make a GET request."""
111
+ return self.request("GET", path, params=params)
112
+
113
+ def post(self, path: str, data: Optional[Dict[str, Any]] = None) -> Response:
114
+ """Make a POST request."""
115
+ return self.request("POST", path, data=data)
116
+
117
+ def put(self, path: str, data: Optional[Dict[str, Any]] = None) -> Response:
118
+ """Make a PUT request."""
119
+ return self.request("PUT", path, data=data)
120
+
121
+ def delete(self, path: str) -> Response:
122
+ """Make a DELETE request."""
123
+ return self.request("DELETE", path)