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.
- agentmemory/__init__.py +131 -0
- agentmemory/client.py +491 -0
- agentmemory/defaults.py +12 -0
- agentmemory/exceptions.py +230 -0
- agentmemory/http.py +827 -0
- agentmemory/logger.py +104 -0
- agentmemory/models.py +346 -0
- agentmemory/py.typed +0 -0
- agentmemory/resources/__init__.py +27 -0
- agentmemory/resources/health.py +251 -0
- agentmemory/resources/session.py +897 -0
- agentmemory/resources/user.py +586 -0
- couchbase_agent_memory-1.0.0.dist-info/METADATA +31 -0
- couchbase_agent_memory-1.0.0.dist-info/RECORD +16 -0
- couchbase_agent_memory-1.0.0.dist-info/WHEEL +5 -0
- couchbase_agent_memory-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -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)
|