couchbase-agent-memory 1.0.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.
@@ -0,0 +1,230 @@
1
+ """
2
+ Custom exceptions for the Couchbase Agent Memory client SDK.
3
+ """
4
+
5
+ from typing import Optional, Dict, Any
6
+
7
+
8
+ class AgentMemoryError(Exception):
9
+ """Base exception for Couchbase Agent Memory SDK errors."""
10
+
11
+ def __init__(
12
+ self,
13
+ message: str,
14
+ status_code: Optional[int] = None,
15
+ details: Optional[Dict[str, Any]] = None,
16
+ ):
17
+ self.message = message
18
+ self.status_code = status_code
19
+ self.details = details or {}
20
+ super().__init__(self.message)
21
+
22
+ def __str__(self) -> str:
23
+ if self.status_code:
24
+ return f"[{self.status_code}] {self.message}"
25
+ return self.message
26
+
27
+
28
+ class AuthenticationError(AgentMemoryError):
29
+ """Raised when authentication or authorization fails.
30
+
31
+ HTTP 401 Unauthorized - Authentication failures:
32
+ - Token is missing when server requires authentication
33
+ - Token is expired
34
+ - Token is invalid or malformed
35
+ - ID token used instead of access token
36
+ - Token claims (iss, aud) don't match server configuration
37
+ - Token validation failed
38
+
39
+ HTTP 403 Forbidden - Authorization failures:
40
+ - User lacks required role/permissions
41
+ - Insufficient permissions for the requested operation
42
+ """
43
+
44
+ def __init__(
45
+ self,
46
+ message: str = "Authentication failed",
47
+ status_code: int = 401,
48
+ ):
49
+ super().__init__(message, status_code=status_code)
50
+
51
+
52
+ class NotFoundError(AgentMemoryError):
53
+ """Raised when a requested resource is not found."""
54
+
55
+ def __init__(
56
+ self,
57
+ message: str = "Resource not found",
58
+ resource_type: Optional[str] = None,
59
+ resource_id: Optional[str] = None,
60
+ ):
61
+ details = {}
62
+ if resource_type:
63
+ details["resource_type"] = resource_type
64
+ if resource_id:
65
+ details["resource_id"] = resource_id
66
+ super().__init__(message, status_code=404, details=details)
67
+
68
+
69
+ class ValidationError(AgentMemoryError):
70
+ """Raised when request validation fails."""
71
+
72
+ def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
73
+ super().__init__(message, status_code=400, details=details)
74
+
75
+
76
+ class ConflictError(AgentMemoryError):
77
+ """Raised when a resource already exists."""
78
+
79
+ def __init__(
80
+ self,
81
+ message: str = "Resource already exists",
82
+ resource_type: Optional[str] = None,
83
+ resource_id: Optional[str] = None,
84
+ ):
85
+ details = {}
86
+ if resource_type:
87
+ details["resource_type"] = resource_type
88
+ if resource_id:
89
+ details["resource_id"] = resource_id
90
+ super().__init__(message, status_code=409, details=details)
91
+
92
+
93
+ class RateLimitError(AgentMemoryError):
94
+ """Raised when rate limit is exceeded."""
95
+
96
+ def __init__(
97
+ self,
98
+ message: str = "Rate limit exceeded",
99
+ retry_after: Optional[float] = None,
100
+ ):
101
+ details = {}
102
+ if retry_after:
103
+ details["retry_after_seconds"] = retry_after
104
+ self.retry_after = retry_after
105
+ super().__init__(message, status_code=429, details=details)
106
+
107
+
108
+ class ServiceUnavailableError(AgentMemoryError):
109
+ """Raised when a required service is unavailable."""
110
+
111
+ def __init__(
112
+ self,
113
+ message: str = "Service unavailable",
114
+ service: Optional[str] = None,
115
+ retry_after: Optional[float] = None,
116
+ ):
117
+ details = {}
118
+ if service:
119
+ details["service"] = service
120
+ if retry_after:
121
+ details["retry_after_seconds"] = retry_after
122
+ self.service = service
123
+ self.retry_after = retry_after
124
+ super().__init__(message, status_code=503, details=details)
125
+
126
+
127
+ class UpstreamError(AgentMemoryError):
128
+ """Raised when an upstream service (embedding, LLM) fails."""
129
+
130
+ def __init__(
131
+ self,
132
+ message: str,
133
+ service: Optional[str] = None,
134
+ retry_after: Optional[float] = None,
135
+ ):
136
+ details = {}
137
+ if service:
138
+ details["service"] = service
139
+ if retry_after:
140
+ details["retry_after_seconds"] = retry_after
141
+ self.service = service
142
+ self.retry_after = retry_after
143
+ super().__init__(message, status_code=502, details=details)
144
+
145
+
146
+ class ServerError(AgentMemoryError):
147
+ """Raised when the server returns an unexpected error."""
148
+
149
+ def __init__(
150
+ self,
151
+ message: str = "Internal server error",
152
+ details: Optional[Dict[str, Any]] = None,
153
+ ):
154
+ super().__init__(message, status_code=500, details=details)
155
+
156
+
157
+ class ConnectionError(AgentMemoryError):
158
+ """Raised when unable to connect to the Couchbase Agent Memory server."""
159
+
160
+ def __init__(
161
+ self, message: str = "Failed to connect to Couchbase Agent Memory server"
162
+ ):
163
+ super().__init__(message)
164
+
165
+
166
+ class TimeoutError(AgentMemoryError):
167
+ """Raised when a request times out.
168
+
169
+ Attributes:
170
+ server_status: Status of the server after timeout. One of:
171
+ - "unknown": Health check was not performed or failed
172
+ - "healthy": Server is up but request took too long (server busy/slow)
173
+ - "unreachable": Server is down or unreachable
174
+ is_server_healthy: True if server responded to health check after timeout
175
+ """
176
+
177
+ def __init__(
178
+ self,
179
+ message: str = "Request timed out",
180
+ server_status: str = "unknown",
181
+ is_server_healthy: Optional[bool] = None,
182
+ ):
183
+ self.server_status = server_status
184
+ self.is_server_healthy = is_server_healthy
185
+
186
+ # Build informative message
187
+ if server_status == "healthy":
188
+ full_message = (
189
+ f"{message} (server is still running - request was slow to process)"
190
+ )
191
+ elif server_status == "unreachable":
192
+ full_message = f"{message} (server appears to be down or unreachable)"
193
+ else:
194
+ full_message = message
195
+
196
+ super().__init__(
197
+ full_message,
198
+ status_code=408,
199
+ details={
200
+ "server_status": server_status,
201
+ "is_server_healthy": is_server_healthy,
202
+ },
203
+ )
204
+
205
+
206
+ class ServerDownError(TimeoutError):
207
+ """Raised when a timeout occurs and the server is confirmed to be down.
208
+
209
+ This exception is raised when:
210
+ 1. A request times out (ReadTimeout)
211
+ 2. A subsequent health check also fails
212
+ """
213
+
214
+ def __init__(self, message: str = "Server is down or unreachable"):
215
+ super().__init__(message, server_status="unreachable", is_server_healthy=False)
216
+
217
+
218
+ class ReadTimeoutError(TimeoutError):
219
+ """Raised when a read timeout occurs but the server is confirmed to be healthy.
220
+
221
+ This exception is raised when:
222
+ 1. A request times out while reading the response (ReadTimeout)
223
+ 2. A subsequent health check succeeds, confirming the server is still running
224
+ """
225
+
226
+ def __init__(
227
+ self,
228
+ message: str = "Request timed out while reading response, but server is healthy",
229
+ ):
230
+ super().__init__(message, server_status="healthy", is_server_healthy=True)