agenticmem 0.1.2.4__tar.gz → 0.1.3.8__tar.gz
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 agenticmem might be problematic. Click here for more details.
- agenticmem-0.1.3.8/PKG-INFO +72 -0
- agenticmem-0.1.3.8/README.md +48 -0
- {agenticmem-0.1.2.4 → agenticmem-0.1.3.8}/agenticmem/__init__.py +5 -1
- agenticmem-0.1.3.8/agenticmem/client.py +531 -0
- {agenticmem-0.1.2.4 → agenticmem-0.1.3.8}/pyproject.toml +3 -2
- agenticmem-0.1.2.4/PKG-INFO +0 -145
- agenticmem-0.1.2.4/README.md +0 -122
- agenticmem-0.1.2.4/agenticmem/client.py +0 -359
- {agenticmem-0.1.2.4 → agenticmem-0.1.3.8}/agenticmem/client_utils.py +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: agenticmem
|
|
3
|
+
Version: 0.1.3.8
|
|
4
|
+
Summary: A Python client for the AgenticMem API
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: AgenticMem Team
|
|
7
|
+
Requires-Python: >=3.10,<4.0
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Dist: agenticmem-commons (==0.1.3.8)
|
|
15
|
+
Requires-Dist: aiohttp (>=3.12.9,<4.0.0)
|
|
16
|
+
Requires-Dist: griffe (==0.48.0)
|
|
17
|
+
Requires-Dist: mkdocs-with-pdf (>=0.9.3,<0.10.0)
|
|
18
|
+
Requires-Dist: mkdocstrings[python] (>=0.18.0)
|
|
19
|
+
Requires-Dist: pydantic (>=2.0.0,<3.0.0)
|
|
20
|
+
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
|
|
21
|
+
Requires-Dist: requests (>=2.25.0,<3.0.0)
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# /user_profiler/agenticmem/agenticmem_client
|
|
25
|
+
Description: Python SDK for remote async access to AgenticMem API
|
|
26
|
+
|
|
27
|
+
## Main Entry Points
|
|
28
|
+
|
|
29
|
+
- **Client**: `agenticmem/client.py` - `AgenticMemClient`
|
|
30
|
+
- **Utils**: `agenticmem/client_utils.py` - Helper utilities
|
|
31
|
+
|
|
32
|
+
## Purpose
|
|
33
|
+
|
|
34
|
+
1. **Remote API access** - Async SDK for applications to call AgenticMem backend
|
|
35
|
+
2. **Authentication** - Handle login and Bearer token management
|
|
36
|
+
3. **Type-safe interface** - Auto-parsing responses into Pydantic models
|
|
37
|
+
|
|
38
|
+
## API Methods
|
|
39
|
+
|
|
40
|
+
**Authentication:**
|
|
41
|
+
- `login(email, password)` - Get auth token
|
|
42
|
+
|
|
43
|
+
**Publishing:**
|
|
44
|
+
- `publish_interaction(request_id, user_id, interactions, source, agent_version)` - Publish interactions (triggers profile/feedback/evaluation)
|
|
45
|
+
|
|
46
|
+
**Profiles:**
|
|
47
|
+
- `search_profiles(request)` - Semantic search
|
|
48
|
+
- `get_profiles(request)` - Get all for user
|
|
49
|
+
- `delete_profile(user_id, profile_id, search_query)` - Delete profiles
|
|
50
|
+
- `get_profile_change_log()` - Get history
|
|
51
|
+
|
|
52
|
+
**Interactions:**
|
|
53
|
+
- `search_interactions(request)` - Semantic search
|
|
54
|
+
- `get_interactions(request)` - Get all for user
|
|
55
|
+
- `delete_interaction(user_id, interaction_id)` - Delete interaction
|
|
56
|
+
|
|
57
|
+
**Feedback:**
|
|
58
|
+
- `get_raw_feedbacks(request)` - Raw feedback from interactions
|
|
59
|
+
- `get_feedbacks(request)` - Aggregated feedback with status
|
|
60
|
+
|
|
61
|
+
**Configuration:**
|
|
62
|
+
- `set_config(config)` - Update org config (extractors, evaluators, storage)
|
|
63
|
+
- `get_config()` - Get current config
|
|
64
|
+
|
|
65
|
+
## Architecture Pattern
|
|
66
|
+
|
|
67
|
+
- **All async** - Uses `aiohttp` for HTTP requests
|
|
68
|
+
- **Type-safe** - Pydantic models from `agenticmem_commons`
|
|
69
|
+
- **Auto-parsing** - Responses → Pydantic models
|
|
70
|
+
- **Flexible input** - Accepts Pydantic models or dicts
|
|
71
|
+
- **Bearer auth** - Automatic token handling
|
|
72
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# /user_profiler/agenticmem/agenticmem_client
|
|
2
|
+
Description: Python SDK for remote async access to AgenticMem API
|
|
3
|
+
|
|
4
|
+
## Main Entry Points
|
|
5
|
+
|
|
6
|
+
- **Client**: `agenticmem/client.py` - `AgenticMemClient`
|
|
7
|
+
- **Utils**: `agenticmem/client_utils.py` - Helper utilities
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
1. **Remote API access** - Async SDK for applications to call AgenticMem backend
|
|
12
|
+
2. **Authentication** - Handle login and Bearer token management
|
|
13
|
+
3. **Type-safe interface** - Auto-parsing responses into Pydantic models
|
|
14
|
+
|
|
15
|
+
## API Methods
|
|
16
|
+
|
|
17
|
+
**Authentication:**
|
|
18
|
+
- `login(email, password)` - Get auth token
|
|
19
|
+
|
|
20
|
+
**Publishing:**
|
|
21
|
+
- `publish_interaction(request_id, user_id, interactions, source, agent_version)` - Publish interactions (triggers profile/feedback/evaluation)
|
|
22
|
+
|
|
23
|
+
**Profiles:**
|
|
24
|
+
- `search_profiles(request)` - Semantic search
|
|
25
|
+
- `get_profiles(request)` - Get all for user
|
|
26
|
+
- `delete_profile(user_id, profile_id, search_query)` - Delete profiles
|
|
27
|
+
- `get_profile_change_log()` - Get history
|
|
28
|
+
|
|
29
|
+
**Interactions:**
|
|
30
|
+
- `search_interactions(request)` - Semantic search
|
|
31
|
+
- `get_interactions(request)` - Get all for user
|
|
32
|
+
- `delete_interaction(user_id, interaction_id)` - Delete interaction
|
|
33
|
+
|
|
34
|
+
**Feedback:**
|
|
35
|
+
- `get_raw_feedbacks(request)` - Raw feedback from interactions
|
|
36
|
+
- `get_feedbacks(request)` - Aggregated feedback with status
|
|
37
|
+
|
|
38
|
+
**Configuration:**
|
|
39
|
+
- `set_config(config)` - Update org config (extractors, evaluators, storage)
|
|
40
|
+
- `get_config()` - Get current config
|
|
41
|
+
|
|
42
|
+
## Architecture Pattern
|
|
43
|
+
|
|
44
|
+
- **All async** - Uses `aiohttp` for HTTP requests
|
|
45
|
+
- **Type-safe** - Pydantic models from `agenticmem_commons`
|
|
46
|
+
- **Auto-parsing** - Responses → Pydantic models
|
|
47
|
+
- **Flexible input** - Accepts Pydantic models or dicts
|
|
48
|
+
- **Bearer auth** - Automatic token handling
|
|
@@ -2,7 +2,7 @@ __app_name__ = "agenticmem"
|
|
|
2
2
|
__version__ = "0.1.1"
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from .client import AgenticMemClient
|
|
6
6
|
from agenticmem_commons.api_schema.service_schemas import (
|
|
7
7
|
UserActionType,
|
|
8
8
|
ProfileTimeToLive,
|
|
@@ -31,6 +31,8 @@ from agenticmem_commons.config_schema import (
|
|
|
31
31
|
ProfileExtractorConfig,
|
|
32
32
|
FeedbackAggregatorConfig,
|
|
33
33
|
AgentFeedbackConfig,
|
|
34
|
+
AgentSuccessConfig,
|
|
35
|
+
ToolUseConfig,
|
|
34
36
|
Config,
|
|
35
37
|
)
|
|
36
38
|
|
|
@@ -63,5 +65,7 @@ __all__ = [
|
|
|
63
65
|
"ProfileExtractorConfig",
|
|
64
66
|
"FeedbackAggregatorConfig",
|
|
65
67
|
"AgentFeedbackConfig",
|
|
68
|
+
"AgentSuccessConfig",
|
|
69
|
+
"ToolUseConfig",
|
|
66
70
|
"Config",
|
|
67
71
|
]
|
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import aiohttp
|
|
3
|
+
import asyncio
|
|
4
|
+
from urllib.parse import urljoin
|
|
5
|
+
import requests
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
7
|
+
from typing import Optional, Union
|
|
8
|
+
from agenticmem_commons.api_schema.retriever_schema import (
|
|
9
|
+
SearchInteractionRequest,
|
|
10
|
+
SearchInteractionResponse,
|
|
11
|
+
SearchUserProfileRequest,
|
|
12
|
+
SearchUserProfileResponse,
|
|
13
|
+
GetInteractionsRequest,
|
|
14
|
+
GetInteractionsResponse,
|
|
15
|
+
GetUserProfilesRequest,
|
|
16
|
+
GetUserProfilesResponse,
|
|
17
|
+
GetRawFeedbacksRequest,
|
|
18
|
+
GetRawFeedbacksResponse,
|
|
19
|
+
GetFeedbacksRequest,
|
|
20
|
+
GetFeedbacksResponse,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from dotenv import load_dotenv
|
|
24
|
+
|
|
25
|
+
# Load environment variables from .env file
|
|
26
|
+
load_dotenv()
|
|
27
|
+
|
|
28
|
+
IS_TEST_ENV = os.environ.get("IS_TEST_ENV", "false").strip() == "true"
|
|
29
|
+
|
|
30
|
+
if IS_TEST_ENV:
|
|
31
|
+
BACKEND_URL = "http://127.0.0.1:8000" # Local server for testing
|
|
32
|
+
else:
|
|
33
|
+
BACKEND_URL = "http://agenticmem-test.us-west-2.elasticbeanstalk.com:8081" # Elastic Beanstalk server url
|
|
34
|
+
|
|
35
|
+
from agenticmem_commons.api_schema.service_schemas import (
|
|
36
|
+
InteractionRequest,
|
|
37
|
+
ProfileChangeLogResponse,
|
|
38
|
+
PublishUserInteractionRequest,
|
|
39
|
+
PublishUserInteractionResponse,
|
|
40
|
+
DeleteUserProfileRequest,
|
|
41
|
+
DeleteUserProfileResponse,
|
|
42
|
+
DeleteUserInteractionRequest,
|
|
43
|
+
DeleteUserInteractionResponse,
|
|
44
|
+
)
|
|
45
|
+
from agenticmem_commons.api_schema.login_schema import Token
|
|
46
|
+
from agenticmem_commons.config_schema import Config
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class AgenticMemClient:
|
|
50
|
+
"""Client for interacting with the AgenticMem API."""
|
|
51
|
+
|
|
52
|
+
# Shared thread pool for all instances to maximize efficiency
|
|
53
|
+
_thread_pool = ThreadPoolExecutor(max_workers=4, thread_name_prefix="agenticmem")
|
|
54
|
+
|
|
55
|
+
def __init__(self, api_key: str = "", url_endpoint: str = ""):
|
|
56
|
+
"""Initialize the AgenticMem client.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
api_key (str): Your API key for authentication
|
|
60
|
+
"""
|
|
61
|
+
self.api_key = api_key
|
|
62
|
+
self.base_url = url_endpoint if url_endpoint else BACKEND_URL
|
|
63
|
+
self.session = requests.Session()
|
|
64
|
+
|
|
65
|
+
def _get_auth_headers(self) -> dict:
|
|
66
|
+
"""Get authentication headers for API requests.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
dict: Headers with authorization and content-type
|
|
70
|
+
"""
|
|
71
|
+
if self.api_key:
|
|
72
|
+
return {
|
|
73
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
74
|
+
"Content-Type": "application/json",
|
|
75
|
+
}
|
|
76
|
+
return {}
|
|
77
|
+
|
|
78
|
+
def _convert_to_model(self, data: Union[dict, object], model_class):
|
|
79
|
+
"""Convert dict to model instance if needed.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
data: Either a dict or already an instance of model_class
|
|
83
|
+
model_class: The target class to convert to
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
An instance of model_class
|
|
87
|
+
"""
|
|
88
|
+
if isinstance(data, dict):
|
|
89
|
+
return model_class(**data)
|
|
90
|
+
return data
|
|
91
|
+
|
|
92
|
+
def _fire_and_forget(self, sync_func, async_func, *args, **kwargs):
|
|
93
|
+
"""Execute a request in fire-and-forget mode.
|
|
94
|
+
|
|
95
|
+
This method optimizes execution based on context:
|
|
96
|
+
- In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
|
|
97
|
+
- In sync contexts: Uses shared thread pool (avoids thread creation overhead)
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
sync_func: Synchronous function to call
|
|
101
|
+
async_func: Asynchronous function to call
|
|
102
|
+
*args: Positional arguments to pass to the function
|
|
103
|
+
**kwargs: Keyword arguments to pass to the function
|
|
104
|
+
"""
|
|
105
|
+
try:
|
|
106
|
+
loop = asyncio.get_running_loop()
|
|
107
|
+
|
|
108
|
+
# We're in an async context - use the event loop
|
|
109
|
+
async def fire_and_forget():
|
|
110
|
+
try:
|
|
111
|
+
await async_func(*args, **kwargs)
|
|
112
|
+
except Exception:
|
|
113
|
+
# Silently ignore errors in fire-and-forget mode
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
loop.create_task(fire_and_forget())
|
|
117
|
+
except RuntimeError:
|
|
118
|
+
# No running loop - we're in sync context, use thread pool
|
|
119
|
+
def send_request():
|
|
120
|
+
try:
|
|
121
|
+
sync_func(*args, **kwargs)
|
|
122
|
+
except Exception:
|
|
123
|
+
# Silently ignore errors in fire-and-forget mode
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
self._thread_pool.submit(send_request)
|
|
127
|
+
|
|
128
|
+
async def _make_async_request(
|
|
129
|
+
self, method: str, endpoint: str, headers: Optional[dict] = None, **kwargs
|
|
130
|
+
):
|
|
131
|
+
"""Make an async HTTP request to the API."""
|
|
132
|
+
url = urljoin(self.base_url, endpoint)
|
|
133
|
+
|
|
134
|
+
# Merge auth headers with any provided headers
|
|
135
|
+
request_headers = self._get_auth_headers()
|
|
136
|
+
if headers:
|
|
137
|
+
request_headers.update(headers)
|
|
138
|
+
|
|
139
|
+
async with aiohttp.ClientSession() as async_session:
|
|
140
|
+
response = await async_session.request(
|
|
141
|
+
method, url, headers=request_headers, **kwargs
|
|
142
|
+
)
|
|
143
|
+
response.raise_for_status()
|
|
144
|
+
return await response.json()
|
|
145
|
+
|
|
146
|
+
def _make_request(
|
|
147
|
+
self, method: str, endpoint: str, headers: Optional[dict] = None, **kwargs
|
|
148
|
+
):
|
|
149
|
+
"""Make an HTTP request to the API.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
method (str): HTTP method (GET, POST, DELETE)
|
|
153
|
+
endpoint (str): API endpoint
|
|
154
|
+
headers (dict, optional): Additional headers to include in the request
|
|
155
|
+
**kwargs: Additional arguments to pass to requests
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
dict: API response
|
|
159
|
+
"""
|
|
160
|
+
url = urljoin(self.base_url, endpoint)
|
|
161
|
+
|
|
162
|
+
# Merge auth headers with any provided headers
|
|
163
|
+
request_headers = self._get_auth_headers()
|
|
164
|
+
if headers:
|
|
165
|
+
request_headers.update(headers)
|
|
166
|
+
|
|
167
|
+
self.session.headers.update(request_headers)
|
|
168
|
+
response = self.session.request(method, url, **kwargs)
|
|
169
|
+
response.raise_for_status()
|
|
170
|
+
return response.json()
|
|
171
|
+
|
|
172
|
+
def login(self, email: str, password: str) -> Token:
|
|
173
|
+
"""Login to the AgenticMem API."""
|
|
174
|
+
response = self._make_request(
|
|
175
|
+
"POST",
|
|
176
|
+
"/token",
|
|
177
|
+
data={"username": email, "password": password},
|
|
178
|
+
headers={
|
|
179
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
180
|
+
"accept": "application/json",
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
return Token(**response)
|
|
184
|
+
|
|
185
|
+
def _publish_interaction_sync(
|
|
186
|
+
self, request: PublishUserInteractionRequest
|
|
187
|
+
) -> PublishUserInteractionResponse:
|
|
188
|
+
"""Internal sync method to publish interaction."""
|
|
189
|
+
response = self._make_request(
|
|
190
|
+
"POST",
|
|
191
|
+
"/api/publish_interaction",
|
|
192
|
+
json=request.model_dump(),
|
|
193
|
+
)
|
|
194
|
+
return PublishUserInteractionResponse(**response)
|
|
195
|
+
|
|
196
|
+
async def _publish_interaction_async(
|
|
197
|
+
self, request: PublishUserInteractionRequest
|
|
198
|
+
) -> PublishUserInteractionResponse:
|
|
199
|
+
"""Internal async method to publish interaction."""
|
|
200
|
+
response = await self._make_async_request(
|
|
201
|
+
"POST",
|
|
202
|
+
"/api/publish_interaction",
|
|
203
|
+
json=request.model_dump(),
|
|
204
|
+
)
|
|
205
|
+
return PublishUserInteractionResponse(**response)
|
|
206
|
+
|
|
207
|
+
def publish_interaction(
|
|
208
|
+
self,
|
|
209
|
+
request_id: str,
|
|
210
|
+
user_id: str,
|
|
211
|
+
interaction_requests: list[Union[InteractionRequest, dict]],
|
|
212
|
+
source: str = "",
|
|
213
|
+
agent_version: str = "",
|
|
214
|
+
wait_for_response: bool = False,
|
|
215
|
+
) -> Optional[PublishUserInteractionResponse]:
|
|
216
|
+
"""Publish user interactions.
|
|
217
|
+
|
|
218
|
+
This method is optimized for resource efficiency:
|
|
219
|
+
- In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
|
|
220
|
+
- In sync contexts: Uses shared thread pool (avoids thread creation overhead)
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
request_id (str): The request ID
|
|
224
|
+
user_id (str): The user ID
|
|
225
|
+
interaction_requests (List[InteractionRequest]): List of interaction requests
|
|
226
|
+
source (str, optional): The source of the interaction
|
|
227
|
+
agent_version (str, optional): The agent version
|
|
228
|
+
wait_for_response (bool, optional): If True, wait for response. If False, send request without waiting. Defaults to False.
|
|
229
|
+
Returns:
|
|
230
|
+
Optional[PublishUserInteractionResponse]: Response containing success status and message if wait_for_response=True, None otherwise
|
|
231
|
+
"""
|
|
232
|
+
interaction_requests = [
|
|
233
|
+
(
|
|
234
|
+
InteractionRequest(**interaction_request)
|
|
235
|
+
if isinstance(interaction_request, dict)
|
|
236
|
+
else interaction_request
|
|
237
|
+
)
|
|
238
|
+
for interaction_request in interaction_requests
|
|
239
|
+
]
|
|
240
|
+
request = PublishUserInteractionRequest(
|
|
241
|
+
request_id=request_id,
|
|
242
|
+
user_id=user_id,
|
|
243
|
+
interaction_requests=interaction_requests,
|
|
244
|
+
source=source,
|
|
245
|
+
agent_version=agent_version,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
if wait_for_response:
|
|
249
|
+
# Synchronous blocking call
|
|
250
|
+
return self._publish_interaction_sync(request)
|
|
251
|
+
else:
|
|
252
|
+
# Non-blocking fire-and-forget
|
|
253
|
+
self._fire_and_forget(
|
|
254
|
+
self._publish_interaction_sync, self._publish_interaction_async, request
|
|
255
|
+
)
|
|
256
|
+
return None
|
|
257
|
+
|
|
258
|
+
def search_interactions(
|
|
259
|
+
self,
|
|
260
|
+
request: Union[SearchInteractionRequest, dict],
|
|
261
|
+
) -> SearchInteractionResponse:
|
|
262
|
+
"""Search for user interactions.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
request (SearchInteractionRequest): The search request
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
SearchInteractionResponse: Response containing matching interactions
|
|
269
|
+
"""
|
|
270
|
+
request = self._convert_to_model(request, SearchInteractionRequest)
|
|
271
|
+
response = self._make_request(
|
|
272
|
+
"POST",
|
|
273
|
+
"/api/search_interactions",
|
|
274
|
+
json=request.model_dump(),
|
|
275
|
+
)
|
|
276
|
+
return SearchInteractionResponse(**response)
|
|
277
|
+
|
|
278
|
+
def search_profiles(
|
|
279
|
+
self,
|
|
280
|
+
request: Union[SearchUserProfileRequest, dict],
|
|
281
|
+
) -> SearchUserProfileResponse:
|
|
282
|
+
"""Search for user profiles.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
request (SearchUserProfileRequest): The search request
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
SearchUserProfileResponse: Response containing matching profiles
|
|
289
|
+
"""
|
|
290
|
+
request = self._convert_to_model(request, SearchUserProfileRequest)
|
|
291
|
+
response = self._make_request(
|
|
292
|
+
"POST", "/api/search_profiles", json=request.model_dump()
|
|
293
|
+
)
|
|
294
|
+
return SearchUserProfileResponse(**response)
|
|
295
|
+
|
|
296
|
+
def _delete_profile_sync(
|
|
297
|
+
self, request: DeleteUserProfileRequest
|
|
298
|
+
) -> DeleteUserProfileResponse:
|
|
299
|
+
"""Internal sync method to delete profile."""
|
|
300
|
+
response = self._make_request(
|
|
301
|
+
"DELETE",
|
|
302
|
+
"/api/delete_profile",
|
|
303
|
+
json=request.model_dump(),
|
|
304
|
+
)
|
|
305
|
+
return DeleteUserProfileResponse(**response)
|
|
306
|
+
|
|
307
|
+
async def _delete_profile_async(
|
|
308
|
+
self, request: DeleteUserProfileRequest
|
|
309
|
+
) -> DeleteUserProfileResponse:
|
|
310
|
+
"""Internal async method to delete profile."""
|
|
311
|
+
response = await self._make_async_request(
|
|
312
|
+
"DELETE",
|
|
313
|
+
"/api/delete_profile",
|
|
314
|
+
json=request.model_dump(),
|
|
315
|
+
)
|
|
316
|
+
return DeleteUserProfileResponse(**response)
|
|
317
|
+
|
|
318
|
+
def delete_profile(
|
|
319
|
+
self,
|
|
320
|
+
user_id: str,
|
|
321
|
+
profile_id: str = "",
|
|
322
|
+
search_query: str = "",
|
|
323
|
+
wait_for_response: bool = False,
|
|
324
|
+
) -> Optional[DeleteUserProfileResponse]:
|
|
325
|
+
"""Delete user profiles.
|
|
326
|
+
|
|
327
|
+
This method is optimized for resource efficiency:
|
|
328
|
+
- In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
|
|
329
|
+
- In sync contexts: Uses shared thread pool (avoids thread creation overhead)
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
user_id (str): The user ID
|
|
333
|
+
profile_id (str, optional): Specific profile ID to delete
|
|
334
|
+
search_query (str, optional): Query to match profiles for deletion
|
|
335
|
+
wait_for_response (bool, optional): If True, wait for response. If False, send request without waiting. Defaults to False.
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
Optional[DeleteUserProfileResponse]: Response containing success status and message if wait_for_response=True, None otherwise
|
|
339
|
+
"""
|
|
340
|
+
request = DeleteUserProfileRequest(
|
|
341
|
+
user_id=user_id,
|
|
342
|
+
profile_id=profile_id,
|
|
343
|
+
search_query=search_query,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
if wait_for_response:
|
|
347
|
+
# Synchronous blocking call
|
|
348
|
+
return self._delete_profile_sync(request)
|
|
349
|
+
else:
|
|
350
|
+
# Non-blocking fire-and-forget
|
|
351
|
+
self._fire_and_forget(
|
|
352
|
+
self._delete_profile_sync, self._delete_profile_async, request
|
|
353
|
+
)
|
|
354
|
+
return None
|
|
355
|
+
|
|
356
|
+
def _delete_interaction_sync(
|
|
357
|
+
self, request: DeleteUserInteractionRequest
|
|
358
|
+
) -> DeleteUserInteractionResponse:
|
|
359
|
+
"""Internal sync method to delete interaction."""
|
|
360
|
+
response = self._make_request(
|
|
361
|
+
"DELETE",
|
|
362
|
+
"/api/delete_interaction",
|
|
363
|
+
json=request.model_dump(),
|
|
364
|
+
)
|
|
365
|
+
return DeleteUserInteractionResponse(**response)
|
|
366
|
+
|
|
367
|
+
async def _delete_interaction_async(
|
|
368
|
+
self, request: DeleteUserInteractionRequest
|
|
369
|
+
) -> DeleteUserInteractionResponse:
|
|
370
|
+
"""Internal async method to delete interaction."""
|
|
371
|
+
response = await self._make_async_request(
|
|
372
|
+
"DELETE",
|
|
373
|
+
"/api/delete_interaction",
|
|
374
|
+
json=request.model_dump(),
|
|
375
|
+
)
|
|
376
|
+
return DeleteUserInteractionResponse(**response)
|
|
377
|
+
|
|
378
|
+
def delete_interaction(
|
|
379
|
+
self, user_id: str, interaction_id: str, wait_for_response: bool = False
|
|
380
|
+
) -> Optional[DeleteUserInteractionResponse]:
|
|
381
|
+
"""Delete a user interaction.
|
|
382
|
+
|
|
383
|
+
This method is optimized for resource efficiency:
|
|
384
|
+
- In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
|
|
385
|
+
- In sync contexts: Uses shared thread pool (avoids thread creation overhead)
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
user_id (str): The user ID
|
|
389
|
+
interaction_id (str): The interaction ID to delete
|
|
390
|
+
wait_for_response (bool, optional): If True, wait for response. If False, send request without waiting. Defaults to False.
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
Optional[DeleteUserInteractionResponse]: Response containing success status and message if wait_for_response=True, None otherwise
|
|
394
|
+
"""
|
|
395
|
+
request = DeleteUserInteractionRequest(
|
|
396
|
+
user_id=user_id, interaction_id=interaction_id
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
if wait_for_response:
|
|
400
|
+
# Synchronous blocking call
|
|
401
|
+
return self._delete_interaction_sync(request)
|
|
402
|
+
else:
|
|
403
|
+
# Non-blocking fire-and-forget
|
|
404
|
+
self._fire_and_forget(
|
|
405
|
+
self._delete_interaction_sync, self._delete_interaction_async, request
|
|
406
|
+
)
|
|
407
|
+
return None
|
|
408
|
+
|
|
409
|
+
def get_profile_change_log(self) -> ProfileChangeLogResponse:
|
|
410
|
+
"""Get profile change log.
|
|
411
|
+
|
|
412
|
+
Returns:
|
|
413
|
+
ProfileChangeLogResponse: Response containing profile change log
|
|
414
|
+
"""
|
|
415
|
+
response = self._make_request("GET", "/api/profile_change_log")
|
|
416
|
+
return ProfileChangeLogResponse(**response)
|
|
417
|
+
|
|
418
|
+
def get_interactions(
|
|
419
|
+
self,
|
|
420
|
+
request: Union[GetInteractionsRequest, dict],
|
|
421
|
+
) -> GetInteractionsResponse:
|
|
422
|
+
"""Get user interactions.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
request (GetInteractionsRequest): The list request
|
|
426
|
+
|
|
427
|
+
Returns:
|
|
428
|
+
GetInteractionsResponse: Response containing list of interactions
|
|
429
|
+
"""
|
|
430
|
+
request = self._convert_to_model(request, GetInteractionsRequest)
|
|
431
|
+
response = self._make_request(
|
|
432
|
+
"POST",
|
|
433
|
+
"/api/get_interactions",
|
|
434
|
+
json=request.model_dump(),
|
|
435
|
+
)
|
|
436
|
+
return GetInteractionsResponse(**response)
|
|
437
|
+
|
|
438
|
+
def get_profiles(
|
|
439
|
+
self,
|
|
440
|
+
request: Union[GetUserProfilesRequest, dict],
|
|
441
|
+
) -> GetUserProfilesResponse:
|
|
442
|
+
"""Get user profiles.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
request (GetUserProfilesRequest): The list request
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
GetUserProfilesResponse: Response containing list of profiles
|
|
449
|
+
"""
|
|
450
|
+
request = self._convert_to_model(request, GetUserProfilesRequest)
|
|
451
|
+
response = self._make_request(
|
|
452
|
+
"POST",
|
|
453
|
+
"/api/get_profiles",
|
|
454
|
+
json=request.model_dump(),
|
|
455
|
+
)
|
|
456
|
+
return GetUserProfilesResponse(**response)
|
|
457
|
+
|
|
458
|
+
def set_config(self, config: Union[Config, dict]) -> dict:
|
|
459
|
+
"""Set configuration for the organization.
|
|
460
|
+
|
|
461
|
+
Args:
|
|
462
|
+
config (Union[Config, dict]): The configuration to set
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
dict: Response containing success status and message
|
|
466
|
+
"""
|
|
467
|
+
config = self._convert_to_model(config, Config)
|
|
468
|
+
response = self._make_request(
|
|
469
|
+
"POST",
|
|
470
|
+
"/api/set_config",
|
|
471
|
+
json=config.model_dump(),
|
|
472
|
+
)
|
|
473
|
+
return response
|
|
474
|
+
|
|
475
|
+
def get_config(self) -> Config:
|
|
476
|
+
"""Get configuration for the organization.
|
|
477
|
+
|
|
478
|
+
Returns:
|
|
479
|
+
Config: The current configuration
|
|
480
|
+
"""
|
|
481
|
+
response = self._make_request(
|
|
482
|
+
"GET",
|
|
483
|
+
"/api/get_config",
|
|
484
|
+
)
|
|
485
|
+
return Config(**response)
|
|
486
|
+
|
|
487
|
+
def get_raw_feedbacks(
|
|
488
|
+
self,
|
|
489
|
+
request: Optional[Union[GetRawFeedbacksRequest, dict]] = None,
|
|
490
|
+
) -> GetRawFeedbacksResponse:
|
|
491
|
+
"""Get raw feedbacks.
|
|
492
|
+
|
|
493
|
+
Args:
|
|
494
|
+
request (Optional[Union[GetRawFeedbacksRequest, dict]]): The get request, defaults to empty request if None
|
|
495
|
+
|
|
496
|
+
Returns:
|
|
497
|
+
GetRawFeedbacksResponse: Response containing raw feedbacks
|
|
498
|
+
"""
|
|
499
|
+
if request is None:
|
|
500
|
+
request = GetRawFeedbacksRequest()
|
|
501
|
+
else:
|
|
502
|
+
request = self._convert_to_model(request, GetRawFeedbacksRequest)
|
|
503
|
+
response = self._make_request(
|
|
504
|
+
"POST",
|
|
505
|
+
"/api/get_raw_feedbacks",
|
|
506
|
+
json=request.model_dump(),
|
|
507
|
+
)
|
|
508
|
+
return GetRawFeedbacksResponse(**response)
|
|
509
|
+
|
|
510
|
+
def get_feedbacks(
|
|
511
|
+
self,
|
|
512
|
+
request: Optional[Union[GetFeedbacksRequest, dict]] = None,
|
|
513
|
+
) -> GetFeedbacksResponse:
|
|
514
|
+
"""Get feedbacks.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
request (Optional[Union[GetFeedbacksRequest, dict]]): The get request, defaults to empty request if None
|
|
518
|
+
|
|
519
|
+
Returns:
|
|
520
|
+
GetFeedbacksResponse: Response containing feedbacks
|
|
521
|
+
"""
|
|
522
|
+
if request is None:
|
|
523
|
+
request = GetFeedbacksRequest()
|
|
524
|
+
else:
|
|
525
|
+
request = self._convert_to_model(request, GetFeedbacksRequest)
|
|
526
|
+
response = self._make_request(
|
|
527
|
+
"POST",
|
|
528
|
+
"/api/get_feedbacks",
|
|
529
|
+
json=request.model_dump(),
|
|
530
|
+
)
|
|
531
|
+
return GetFeedbacksResponse(**response)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "agenticmem"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.3.8"
|
|
4
4
|
description = "A Python client for the AgenticMem API"
|
|
5
5
|
authors = ["AgenticMem Team"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -12,10 +12,11 @@ python = "^3.10"
|
|
|
12
12
|
requests = "^2.25.0"
|
|
13
13
|
pydantic = "^2.0.0"
|
|
14
14
|
python-dateutil = "^2.8.0"
|
|
15
|
-
agenticmem-commons = "0.1.3.
|
|
15
|
+
agenticmem-commons = "0.1.3.8"
|
|
16
16
|
mkdocstrings = {version = ">=0.18.0", extras = ["python"]}
|
|
17
17
|
griffe = "0.48.0"
|
|
18
18
|
aiohttp = "^3.12.9"
|
|
19
|
+
mkdocs-with-pdf = "^0.9.3"
|
|
19
20
|
|
|
20
21
|
[build-system]
|
|
21
22
|
requires = ["poetry-core>=1.0.0"]
|
agenticmem-0.1.2.4/PKG-INFO
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: agenticmem
|
|
3
|
-
Version: 0.1.2.4
|
|
4
|
-
Summary: A Python client for the AgenticMem API
|
|
5
|
-
License: MIT
|
|
6
|
-
Author: AgenticMem Team
|
|
7
|
-
Requires-Python: >=3.10,<4.0
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
-
Requires-Dist: agenticmem-commons (==0.1.3.6)
|
|
15
|
-
Requires-Dist: aiohttp (>=3.12.9,<4.0.0)
|
|
16
|
-
Requires-Dist: griffe (==0.48.0)
|
|
17
|
-
Requires-Dist: mkdocstrings[python] (>=0.18.0)
|
|
18
|
-
Requires-Dist: pydantic (>=2.0.0,<3.0.0)
|
|
19
|
-
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
|
|
20
|
-
Requires-Dist: requests (>=2.25.0,<3.0.0)
|
|
21
|
-
Description-Content-Type: text/markdown
|
|
22
|
-
|
|
23
|
-
# AgenticMem Python Client
|
|
24
|
-
|
|
25
|
-
A Python client library for interacting with the AgenticMem API. This client provides easy-to-use interfaces for managing user interactions and profiles.
|
|
26
|
-
|
|
27
|
-
## Installation
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
pip install agenticmem
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Quick Start
|
|
34
|
-
|
|
35
|
-
```python
|
|
36
|
-
from agenticmem import AgenticMemClient
|
|
37
|
-
from agenticmem_commons.api_schema.service_schemas import InteractionRequest
|
|
38
|
-
from agenticmem_commons.api_schema.retriever_schema import (
|
|
39
|
-
SearchInteractionRequest,
|
|
40
|
-
SearchUserProfileRequest,
|
|
41
|
-
GetInteractionsRequest,
|
|
42
|
-
GetUserProfilesRequest
|
|
43
|
-
)
|
|
44
|
-
from datetime import datetime
|
|
45
|
-
|
|
46
|
-
# Initialize the client
|
|
47
|
-
client = AgenticMemClient(api_key="your_api_key")
|
|
48
|
-
|
|
49
|
-
# Optional: Login with email/password
|
|
50
|
-
token = client.login(email="user@example.com", password="password123")
|
|
51
|
-
|
|
52
|
-
# Publish a user interaction
|
|
53
|
-
interaction = InteractionRequest(
|
|
54
|
-
created_at=int(datetime.utcnow().timestamp()),
|
|
55
|
-
content="User clicked on product X",
|
|
56
|
-
user_action="click",
|
|
57
|
-
user_action_description="Clicked on product details button"
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
response = client.publish_interaction(
|
|
61
|
-
user_id="user123",
|
|
62
|
-
request_id="req456",
|
|
63
|
-
interaction_requests=[interaction]
|
|
64
|
-
)
|
|
65
|
-
print(f"Published interaction: {response.success} - {response.message}")
|
|
66
|
-
|
|
67
|
-
# Search user profiles
|
|
68
|
-
profiles_request = SearchUserProfileRequest(
|
|
69
|
-
user_id="user123",
|
|
70
|
-
search_query="recent interactions",
|
|
71
|
-
top_k=5
|
|
72
|
-
)
|
|
73
|
-
profiles = client.search_profiles(profiles_request)
|
|
74
|
-
for profile in profiles.profiles:
|
|
75
|
-
print(f"Profile {profile.profile_id}: {profile.profile_content}")
|
|
76
|
-
|
|
77
|
-
# Get user profiles directly
|
|
78
|
-
profiles_request = GetUserProfilesRequest(
|
|
79
|
-
user_id="user123"
|
|
80
|
-
)
|
|
81
|
-
profiles = client.get_profiles(profiles_request)
|
|
82
|
-
for profile in profiles.profiles:
|
|
83
|
-
print(f"Profile: {profile}")
|
|
84
|
-
|
|
85
|
-
# Search interactions
|
|
86
|
-
interactions_request = SearchInteractionRequest(
|
|
87
|
-
user_id="user123",
|
|
88
|
-
start_time=int(datetime(2024, 1, 1).timestamp()),
|
|
89
|
-
end_time=int(datetime.utcnow().timestamp())
|
|
90
|
-
)
|
|
91
|
-
interactions = client.search_interactions(interactions_request)
|
|
92
|
-
for interaction in interactions.interactions:
|
|
93
|
-
print(f"Interaction {interaction.interaction_id}: {interaction.content}")
|
|
94
|
-
|
|
95
|
-
# Get interactions directly
|
|
96
|
-
interactions_request = GetInteractionsRequest(
|
|
97
|
-
user_id="user123"
|
|
98
|
-
)
|
|
99
|
-
interactions = client.get_interactions(interactions_request)
|
|
100
|
-
for interaction in interactions.interactions:
|
|
101
|
-
print(f"Interaction: {interaction}")
|
|
102
|
-
|
|
103
|
-
# Get profile change log
|
|
104
|
-
change_log = client.get_profile_change_log()
|
|
105
|
-
print(f"Profile changes: {change_log}")
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Features
|
|
109
|
-
|
|
110
|
-
- Authentication
|
|
111
|
-
- API key authentication
|
|
112
|
-
- Email/password login
|
|
113
|
-
- User interaction management
|
|
114
|
-
- Publish user interactions
|
|
115
|
-
- Delete specific interactions
|
|
116
|
-
- Search interactions with time range and filters
|
|
117
|
-
- Get direct list of interactions
|
|
118
|
-
- User profile management
|
|
119
|
-
- Search user profiles with customizable queries
|
|
120
|
-
- Get direct list of user profiles
|
|
121
|
-
- Delete specific profiles or profiles matching a search query
|
|
122
|
-
- View profile change log history
|
|
123
|
-
|
|
124
|
-
## API Response Types
|
|
125
|
-
|
|
126
|
-
All API methods return strongly-typed responses:
|
|
127
|
-
|
|
128
|
-
- `login()` returns `Token`
|
|
129
|
-
- `publish_interaction()` returns `PublishUserInteractionResponse`
|
|
130
|
-
- `search_interactions()` returns `SearchInteractionResponse`
|
|
131
|
-
- `get_interactions()` returns `GetInteractionsResponse`
|
|
132
|
-
- `search_profiles()` returns `SearchUserProfileResponse`
|
|
133
|
-
- `get_profiles()` returns `GetUserProfilesResponse`
|
|
134
|
-
- `delete_profile()` returns `DeleteUserProfileResponse`
|
|
135
|
-
- `delete_interaction()` returns `DeleteUserInteractionResponse`
|
|
136
|
-
- `get_profile_change_log()` returns `ProfileChangeLogResponse`
|
|
137
|
-
|
|
138
|
-
## Documentation
|
|
139
|
-
|
|
140
|
-
For detailed documentation, please visit [docs link].
|
|
141
|
-
|
|
142
|
-
## License
|
|
143
|
-
|
|
144
|
-
MIT License
|
|
145
|
-
|
agenticmem-0.1.2.4/README.md
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
# AgenticMem Python Client
|
|
2
|
-
|
|
3
|
-
A Python client library for interacting with the AgenticMem API. This client provides easy-to-use interfaces for managing user interactions and profiles.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pip install agenticmem
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
```python
|
|
14
|
-
from agenticmem import AgenticMemClient
|
|
15
|
-
from agenticmem_commons.api_schema.service_schemas import InteractionRequest
|
|
16
|
-
from agenticmem_commons.api_schema.retriever_schema import (
|
|
17
|
-
SearchInteractionRequest,
|
|
18
|
-
SearchUserProfileRequest,
|
|
19
|
-
GetInteractionsRequest,
|
|
20
|
-
GetUserProfilesRequest
|
|
21
|
-
)
|
|
22
|
-
from datetime import datetime
|
|
23
|
-
|
|
24
|
-
# Initialize the client
|
|
25
|
-
client = AgenticMemClient(api_key="your_api_key")
|
|
26
|
-
|
|
27
|
-
# Optional: Login with email/password
|
|
28
|
-
token = client.login(email="user@example.com", password="password123")
|
|
29
|
-
|
|
30
|
-
# Publish a user interaction
|
|
31
|
-
interaction = InteractionRequest(
|
|
32
|
-
created_at=int(datetime.utcnow().timestamp()),
|
|
33
|
-
content="User clicked on product X",
|
|
34
|
-
user_action="click",
|
|
35
|
-
user_action_description="Clicked on product details button"
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
response = client.publish_interaction(
|
|
39
|
-
user_id="user123",
|
|
40
|
-
request_id="req456",
|
|
41
|
-
interaction_requests=[interaction]
|
|
42
|
-
)
|
|
43
|
-
print(f"Published interaction: {response.success} - {response.message}")
|
|
44
|
-
|
|
45
|
-
# Search user profiles
|
|
46
|
-
profiles_request = SearchUserProfileRequest(
|
|
47
|
-
user_id="user123",
|
|
48
|
-
search_query="recent interactions",
|
|
49
|
-
top_k=5
|
|
50
|
-
)
|
|
51
|
-
profiles = client.search_profiles(profiles_request)
|
|
52
|
-
for profile in profiles.profiles:
|
|
53
|
-
print(f"Profile {profile.profile_id}: {profile.profile_content}")
|
|
54
|
-
|
|
55
|
-
# Get user profiles directly
|
|
56
|
-
profiles_request = GetUserProfilesRequest(
|
|
57
|
-
user_id="user123"
|
|
58
|
-
)
|
|
59
|
-
profiles = client.get_profiles(profiles_request)
|
|
60
|
-
for profile in profiles.profiles:
|
|
61
|
-
print(f"Profile: {profile}")
|
|
62
|
-
|
|
63
|
-
# Search interactions
|
|
64
|
-
interactions_request = SearchInteractionRequest(
|
|
65
|
-
user_id="user123",
|
|
66
|
-
start_time=int(datetime(2024, 1, 1).timestamp()),
|
|
67
|
-
end_time=int(datetime.utcnow().timestamp())
|
|
68
|
-
)
|
|
69
|
-
interactions = client.search_interactions(interactions_request)
|
|
70
|
-
for interaction in interactions.interactions:
|
|
71
|
-
print(f"Interaction {interaction.interaction_id}: {interaction.content}")
|
|
72
|
-
|
|
73
|
-
# Get interactions directly
|
|
74
|
-
interactions_request = GetInteractionsRequest(
|
|
75
|
-
user_id="user123"
|
|
76
|
-
)
|
|
77
|
-
interactions = client.get_interactions(interactions_request)
|
|
78
|
-
for interaction in interactions.interactions:
|
|
79
|
-
print(f"Interaction: {interaction}")
|
|
80
|
-
|
|
81
|
-
# Get profile change log
|
|
82
|
-
change_log = client.get_profile_change_log()
|
|
83
|
-
print(f"Profile changes: {change_log}")
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Features
|
|
87
|
-
|
|
88
|
-
- Authentication
|
|
89
|
-
- API key authentication
|
|
90
|
-
- Email/password login
|
|
91
|
-
- User interaction management
|
|
92
|
-
- Publish user interactions
|
|
93
|
-
- Delete specific interactions
|
|
94
|
-
- Search interactions with time range and filters
|
|
95
|
-
- Get direct list of interactions
|
|
96
|
-
- User profile management
|
|
97
|
-
- Search user profiles with customizable queries
|
|
98
|
-
- Get direct list of user profiles
|
|
99
|
-
- Delete specific profiles or profiles matching a search query
|
|
100
|
-
- View profile change log history
|
|
101
|
-
|
|
102
|
-
## API Response Types
|
|
103
|
-
|
|
104
|
-
All API methods return strongly-typed responses:
|
|
105
|
-
|
|
106
|
-
- `login()` returns `Token`
|
|
107
|
-
- `publish_interaction()` returns `PublishUserInteractionResponse`
|
|
108
|
-
- `search_interactions()` returns `SearchInteractionResponse`
|
|
109
|
-
- `get_interactions()` returns `GetInteractionsResponse`
|
|
110
|
-
- `search_profiles()` returns `SearchUserProfileResponse`
|
|
111
|
-
- `get_profiles()` returns `GetUserProfilesResponse`
|
|
112
|
-
- `delete_profile()` returns `DeleteUserProfileResponse`
|
|
113
|
-
- `delete_interaction()` returns `DeleteUserInteractionResponse`
|
|
114
|
-
- `get_profile_change_log()` returns `ProfileChangeLogResponse`
|
|
115
|
-
|
|
116
|
-
## Documentation
|
|
117
|
-
|
|
118
|
-
For detailed documentation, please visit [docs link].
|
|
119
|
-
|
|
120
|
-
## License
|
|
121
|
-
|
|
122
|
-
MIT License
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
from agenticmem_commons import IS_TEST_ENV
|
|
2
|
-
import aiohttp
|
|
3
|
-
from urllib.parse import urljoin
|
|
4
|
-
import requests
|
|
5
|
-
from typing import Optional, Union
|
|
6
|
-
from agenticmem_commons.api_schema.retriever_schema import (
|
|
7
|
-
SearchInteractionRequest,
|
|
8
|
-
SearchInteractionResponse,
|
|
9
|
-
SearchUserProfileRequest,
|
|
10
|
-
SearchUserProfileResponse,
|
|
11
|
-
GetInteractionsRequest,
|
|
12
|
-
GetInteractionsResponse,
|
|
13
|
-
GetUserProfilesRequest,
|
|
14
|
-
GetUserProfilesResponse,
|
|
15
|
-
GetRawFeedbacksRequest,
|
|
16
|
-
GetRawFeedbacksResponse,
|
|
17
|
-
GetFeedbacksRequest,
|
|
18
|
-
GetFeedbacksResponse,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
if IS_TEST_ENV:
|
|
22
|
-
BACKEND_URL = "http://127.0.0.1:8000" # Local server for testing
|
|
23
|
-
else:
|
|
24
|
-
BACKEND_URL = "http://agenticmem-test.us-west-2.elasticbeanstalk.com:8081" # Elastic Beanstalk server url
|
|
25
|
-
|
|
26
|
-
from agenticmem_commons.api_schema.service_schemas import (
|
|
27
|
-
InteractionRequest,
|
|
28
|
-
ProfileChangeLogResponse,
|
|
29
|
-
PublishUserInteractionRequest,
|
|
30
|
-
PublishUserInteractionResponse,
|
|
31
|
-
DeleteUserProfileRequest,
|
|
32
|
-
DeleteUserProfileResponse,
|
|
33
|
-
DeleteUserInteractionRequest,
|
|
34
|
-
DeleteUserInteractionResponse,
|
|
35
|
-
)
|
|
36
|
-
from agenticmem_commons.api_schema.login_schema import Token
|
|
37
|
-
from agenticmem_commons.config_schema import Config
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class AgenticMemClient:
|
|
41
|
-
"""Client for interacting with the AgenticMem API."""
|
|
42
|
-
|
|
43
|
-
def __init__(self, api_key: str = "", url_endpoint: str = ""):
|
|
44
|
-
"""Initialize the AgenticMem client.
|
|
45
|
-
|
|
46
|
-
Args:
|
|
47
|
-
api_key (str): Your API key for authentication
|
|
48
|
-
"""
|
|
49
|
-
self.api_key = api_key
|
|
50
|
-
self.base_url = url_endpoint if url_endpoint else BACKEND_URL
|
|
51
|
-
self.session = requests.Session()
|
|
52
|
-
|
|
53
|
-
async def _make_async_request(
|
|
54
|
-
self, method: str, endpoint: str, headers: Optional[dict] = None, **kwargs
|
|
55
|
-
):
|
|
56
|
-
"""Make an async HTTP request to the API."""
|
|
57
|
-
url = urljoin(self.base_url, endpoint)
|
|
58
|
-
|
|
59
|
-
headers = headers or {}
|
|
60
|
-
if self.api_key:
|
|
61
|
-
headers.update(
|
|
62
|
-
{
|
|
63
|
-
"Authorization": f"Bearer {self.api_key}",
|
|
64
|
-
"Content-Type": "application/json",
|
|
65
|
-
}
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
async with aiohttp.ClientSession() as async_session:
|
|
69
|
-
response = await async_session.request(
|
|
70
|
-
method, url, headers=headers, **kwargs
|
|
71
|
-
)
|
|
72
|
-
response.raise_for_status()
|
|
73
|
-
return await response.json()
|
|
74
|
-
|
|
75
|
-
def _make_request(
|
|
76
|
-
self, method: str, endpoint: str, headers: Optional[dict] = None, **kwargs
|
|
77
|
-
):
|
|
78
|
-
"""Make an HTTP request to the API.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
method (str): HTTP method (GET, POST, DELETE)
|
|
82
|
-
endpoint (str): API endpoint
|
|
83
|
-
headers (dict, optional): Additional headers to include in the request
|
|
84
|
-
**kwargs: Additional arguments to pass to requests
|
|
85
|
-
|
|
86
|
-
Returns:
|
|
87
|
-
dict: API response
|
|
88
|
-
"""
|
|
89
|
-
url = urljoin(self.base_url, endpoint)
|
|
90
|
-
if self.api_key:
|
|
91
|
-
self.session.headers.update(
|
|
92
|
-
{
|
|
93
|
-
"Authorization": f"Bearer {self.api_key}",
|
|
94
|
-
"Content-Type": "application/json",
|
|
95
|
-
}
|
|
96
|
-
)
|
|
97
|
-
if headers:
|
|
98
|
-
self.session.headers.update(headers)
|
|
99
|
-
response = self.session.request(method, url, **kwargs)
|
|
100
|
-
response.raise_for_status()
|
|
101
|
-
return response.json()
|
|
102
|
-
|
|
103
|
-
async def login(self, email: str, password: str) -> Token:
|
|
104
|
-
"""Async login to the AgenticMem API."""
|
|
105
|
-
response = await self._make_async_request(
|
|
106
|
-
"POST",
|
|
107
|
-
"/token",
|
|
108
|
-
data={"username": email, "password": password},
|
|
109
|
-
headers={
|
|
110
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
111
|
-
"accept": "application/json",
|
|
112
|
-
},
|
|
113
|
-
)
|
|
114
|
-
return Token(**response)
|
|
115
|
-
|
|
116
|
-
async def publish_interaction(
|
|
117
|
-
self,
|
|
118
|
-
request_id: str,
|
|
119
|
-
user_id: str,
|
|
120
|
-
interaction_requests: list[Union[InteractionRequest, dict]],
|
|
121
|
-
source: str = "",
|
|
122
|
-
agent_version: str = "",
|
|
123
|
-
) -> PublishUserInteractionResponse:
|
|
124
|
-
"""Publish user interactions.
|
|
125
|
-
|
|
126
|
-
Args:
|
|
127
|
-
request_id (str): The request ID
|
|
128
|
-
user_id (str): The user ID
|
|
129
|
-
interaction_requests (List[InteractionRequest]): List of interaction requests
|
|
130
|
-
source (str, optional): The source of the interaction
|
|
131
|
-
Returns:
|
|
132
|
-
PublishUserInteractionResponse: Response containing success status and message
|
|
133
|
-
"""
|
|
134
|
-
interaction_requests = [
|
|
135
|
-
(
|
|
136
|
-
InteractionRequest(**interaction_request)
|
|
137
|
-
if isinstance(interaction_request, dict)
|
|
138
|
-
else interaction_request
|
|
139
|
-
)
|
|
140
|
-
for interaction_request in interaction_requests
|
|
141
|
-
]
|
|
142
|
-
request = PublishUserInteractionRequest(
|
|
143
|
-
request_id=request_id,
|
|
144
|
-
user_id=user_id,
|
|
145
|
-
interaction_requests=interaction_requests,
|
|
146
|
-
source=source,
|
|
147
|
-
agent_version=agent_version,
|
|
148
|
-
)
|
|
149
|
-
response = await self._make_async_request(
|
|
150
|
-
"POST",
|
|
151
|
-
"/api/publish_interaction",
|
|
152
|
-
json=request.model_dump(),
|
|
153
|
-
)
|
|
154
|
-
return PublishUserInteractionResponse(**response)
|
|
155
|
-
|
|
156
|
-
async def search_interactions(
|
|
157
|
-
self,
|
|
158
|
-
request: Union[SearchInteractionRequest, dict],
|
|
159
|
-
) -> SearchInteractionResponse:
|
|
160
|
-
"""Search for user interactions.
|
|
161
|
-
|
|
162
|
-
Args:
|
|
163
|
-
request (SearchInteractionRequest): The search request
|
|
164
|
-
|
|
165
|
-
Returns:
|
|
166
|
-
SearchInteractionResponse: Response containing matching interactions
|
|
167
|
-
"""
|
|
168
|
-
if isinstance(request, dict):
|
|
169
|
-
request = SearchInteractionRequest(**request)
|
|
170
|
-
response = await self._make_async_request(
|
|
171
|
-
"POST",
|
|
172
|
-
"/api/search_interactions",
|
|
173
|
-
json=request.model_dump(),
|
|
174
|
-
)
|
|
175
|
-
return SearchInteractionResponse(**response)
|
|
176
|
-
|
|
177
|
-
async def search_profiles(
|
|
178
|
-
self,
|
|
179
|
-
request: Union[SearchUserProfileRequest, dict],
|
|
180
|
-
) -> SearchUserProfileResponse:
|
|
181
|
-
"""Search for user profiles.
|
|
182
|
-
|
|
183
|
-
Args:
|
|
184
|
-
request (SearchUserProfileRequest): The search request
|
|
185
|
-
|
|
186
|
-
Returns:
|
|
187
|
-
SearchUserProfileResponse: Response containing matching profiles
|
|
188
|
-
"""
|
|
189
|
-
if isinstance(request, dict):
|
|
190
|
-
request = SearchUserProfileRequest(**request)
|
|
191
|
-
response = await self._make_async_request(
|
|
192
|
-
"POST", "/api/search_profiles", json=request.model_dump()
|
|
193
|
-
)
|
|
194
|
-
return SearchUserProfileResponse(**response)
|
|
195
|
-
|
|
196
|
-
async def delete_profile(
|
|
197
|
-
self, user_id: str, profile_id: str = "", search_query: str = ""
|
|
198
|
-
) -> DeleteUserProfileResponse:
|
|
199
|
-
"""Delete user profiles.
|
|
200
|
-
|
|
201
|
-
Args:
|
|
202
|
-
user_id (str): The user ID
|
|
203
|
-
profile_id (str, optional): Specific profile ID to delete
|
|
204
|
-
search_query (str, optional): Query to match profiles for deletion
|
|
205
|
-
|
|
206
|
-
Returns:
|
|
207
|
-
DeleteUserProfileResponse: Response containing success status and message
|
|
208
|
-
"""
|
|
209
|
-
request = DeleteUserProfileRequest(
|
|
210
|
-
user_id=user_id,
|
|
211
|
-
profile_id=profile_id,
|
|
212
|
-
search_query=search_query,
|
|
213
|
-
)
|
|
214
|
-
response = await self._make_async_request(
|
|
215
|
-
"DELETE", "/api/delete_profile", json=request.model_dump()
|
|
216
|
-
)
|
|
217
|
-
return DeleteUserProfileResponse(**response)
|
|
218
|
-
|
|
219
|
-
async def delete_interaction(
|
|
220
|
-
self, user_id: str, interaction_id: str
|
|
221
|
-
) -> DeleteUserInteractionResponse:
|
|
222
|
-
"""Delete a user interaction.
|
|
223
|
-
|
|
224
|
-
Args:
|
|
225
|
-
user_id (str): The user ID
|
|
226
|
-
interaction_id (str): The interaction ID to delete
|
|
227
|
-
|
|
228
|
-
Returns:
|
|
229
|
-
DeleteUserInteractionResponse: Response containing success status and message
|
|
230
|
-
"""
|
|
231
|
-
request = DeleteUserInteractionRequest(
|
|
232
|
-
user_id=user_id, interaction_id=interaction_id
|
|
233
|
-
)
|
|
234
|
-
response = await self._make_async_request(
|
|
235
|
-
"DELETE", "/api/delete_interaction", json=request.model_dump()
|
|
236
|
-
)
|
|
237
|
-
return DeleteUserInteractionResponse(**response)
|
|
238
|
-
|
|
239
|
-
async def get_profile_change_log(self) -> ProfileChangeLogResponse:
|
|
240
|
-
response = await self._make_async_request("GET", "/api/profile_change_log")
|
|
241
|
-
return ProfileChangeLogResponse(**response)
|
|
242
|
-
|
|
243
|
-
async def get_interactions(
|
|
244
|
-
self,
|
|
245
|
-
request: Union[GetInteractionsRequest, dict],
|
|
246
|
-
) -> GetInteractionsResponse:
|
|
247
|
-
"""Get user interactions.
|
|
248
|
-
|
|
249
|
-
Args:
|
|
250
|
-
request (GetInteractionsRequest): The list request
|
|
251
|
-
|
|
252
|
-
Returns:
|
|
253
|
-
GetInteractionsResponse: Response containing list of interactions
|
|
254
|
-
"""
|
|
255
|
-
if isinstance(request, dict):
|
|
256
|
-
request = GetInteractionsRequest(**request)
|
|
257
|
-
response = await self._make_async_request(
|
|
258
|
-
"POST",
|
|
259
|
-
"/api/get_interactions",
|
|
260
|
-
json=request.model_dump(),
|
|
261
|
-
)
|
|
262
|
-
return GetInteractionsResponse(**response)
|
|
263
|
-
|
|
264
|
-
async def get_profiles(
|
|
265
|
-
self,
|
|
266
|
-
request: Union[GetUserProfilesRequest, dict],
|
|
267
|
-
) -> GetUserProfilesResponse:
|
|
268
|
-
"""Get user profiles.
|
|
269
|
-
|
|
270
|
-
Args:
|
|
271
|
-
request (GetUserProfilesRequest): The list request
|
|
272
|
-
|
|
273
|
-
Returns:
|
|
274
|
-
GetUserProfilesResponse: Response containing list of profiles
|
|
275
|
-
"""
|
|
276
|
-
if isinstance(request, dict):
|
|
277
|
-
request = GetUserProfilesRequest(**request)
|
|
278
|
-
response = await self._make_async_request(
|
|
279
|
-
"POST",
|
|
280
|
-
"/api/get_profiles",
|
|
281
|
-
json=request.model_dump(),
|
|
282
|
-
)
|
|
283
|
-
return GetUserProfilesResponse(**response)
|
|
284
|
-
|
|
285
|
-
async def set_config(self, config: Union[Config, dict]) -> dict:
|
|
286
|
-
"""Set configuration for the organization.
|
|
287
|
-
|
|
288
|
-
Args:
|
|
289
|
-
config (Union[Config, dict]): The configuration to set
|
|
290
|
-
|
|
291
|
-
Returns:
|
|
292
|
-
dict: Response containing success status and message
|
|
293
|
-
"""
|
|
294
|
-
if isinstance(config, dict):
|
|
295
|
-
config = Config(**config)
|
|
296
|
-
response = await self._make_async_request(
|
|
297
|
-
"POST",
|
|
298
|
-
"/api/set_config",
|
|
299
|
-
json=config.model_dump(),
|
|
300
|
-
)
|
|
301
|
-
return response
|
|
302
|
-
|
|
303
|
-
async def get_config(self) -> Config:
|
|
304
|
-
"""Get configuration for the organization.
|
|
305
|
-
|
|
306
|
-
Returns:
|
|
307
|
-
Config: The current configuration
|
|
308
|
-
"""
|
|
309
|
-
response = await self._make_async_request(
|
|
310
|
-
"GET",
|
|
311
|
-
"/api/get_config",
|
|
312
|
-
)
|
|
313
|
-
return Config(**response)
|
|
314
|
-
|
|
315
|
-
async def get_raw_feedbacks(
|
|
316
|
-
self,
|
|
317
|
-
request: Optional[Union[GetRawFeedbacksRequest, dict]] = None,
|
|
318
|
-
) -> GetRawFeedbacksResponse:
|
|
319
|
-
"""Get raw feedbacks.
|
|
320
|
-
|
|
321
|
-
Args:
|
|
322
|
-
request (Optional[Union[GetRawFeedbacksRequest, dict]]): The get request, defaults to empty request if None
|
|
323
|
-
|
|
324
|
-
Returns:
|
|
325
|
-
GetRawFeedbacksResponse: Response containing raw feedbacks
|
|
326
|
-
"""
|
|
327
|
-
if request is None:
|
|
328
|
-
request = GetRawFeedbacksRequest()
|
|
329
|
-
elif isinstance(request, dict):
|
|
330
|
-
request = GetRawFeedbacksRequest(**request)
|
|
331
|
-
response = await self._make_async_request(
|
|
332
|
-
"POST",
|
|
333
|
-
"/api/get_raw_feedbacks",
|
|
334
|
-
json=request.model_dump(),
|
|
335
|
-
)
|
|
336
|
-
return GetRawFeedbacksResponse(**response)
|
|
337
|
-
|
|
338
|
-
async def get_feedbacks(
|
|
339
|
-
self,
|
|
340
|
-
request: Optional[Union[GetFeedbacksRequest, dict]] = None,
|
|
341
|
-
) -> GetFeedbacksResponse:
|
|
342
|
-
"""Get feedbacks.
|
|
343
|
-
|
|
344
|
-
Args:
|
|
345
|
-
request (Optional[Union[GetFeedbacksRequest, dict]]): The get request, defaults to empty request if None
|
|
346
|
-
|
|
347
|
-
Returns:
|
|
348
|
-
GetFeedbacksResponse: Response containing feedbacks
|
|
349
|
-
"""
|
|
350
|
-
if request is None:
|
|
351
|
-
request = GetFeedbacksRequest()
|
|
352
|
-
elif isinstance(request, dict):
|
|
353
|
-
request = GetFeedbacksRequest(**request)
|
|
354
|
-
response = await self._make_async_request(
|
|
355
|
-
"POST",
|
|
356
|
-
"/api/get_feedbacks",
|
|
357
|
-
json=request.model_dump(),
|
|
358
|
-
)
|
|
359
|
-
return GetFeedbacksResponse(**response)
|
|
File without changes
|