hebbrix 2.0.2__tar.gz → 2.0.3__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.
- {hebbrix-2.0.2 → hebbrix-2.0.3}/PKG-INFO +1 -1
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix/__init__.py +1 -1
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix/chat.py +17 -5
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix/client.py +18 -23
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix/resources.py +75 -10
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix.egg-info/PKG-INFO +1 -1
- {hebbrix-2.0.2 → hebbrix-2.0.3}/pyproject.toml +1 -1
- {hebbrix-2.0.2 → hebbrix-2.0.3}/setup.py +1 -1
- {hebbrix-2.0.2 → hebbrix-2.0.3}/MANIFEST.in +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/README.md +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix/exceptions.py +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix.egg-info/SOURCES.txt +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix.egg-info/dependency_links.txt +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix.egg-info/requires.txt +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/hebbrix.egg-info/top_level.txt +0 -0
- {hebbrix-2.0.2 → hebbrix-2.0.3}/setup.cfg +0 -0
|
@@ -9,9 +9,10 @@ Example:
|
|
|
9
9
|
chat = MemoryChat(api_key="mem_sk_...")
|
|
10
10
|
response = chat.send("What's my favorite food?", session_id="user_123")
|
|
11
11
|
"""
|
|
12
|
-
from typing import Optional, Dict, Any, List
|
|
13
|
-
import requests
|
|
14
12
|
|
|
13
|
+
from typing import Any, Dict, List, Optional
|
|
14
|
+
|
|
15
|
+
import requests
|
|
15
16
|
from hebbrix.client import MemoryClient
|
|
16
17
|
|
|
17
18
|
|
|
@@ -53,6 +54,7 @@ class MemoryChat:
|
|
|
53
54
|
learning: Enable RL trajectory logging (default: True)
|
|
54
55
|
prompt_strategy: Prompt template strategy (default: "default")
|
|
55
56
|
memory_limit: Max memories to retrieve per message (default: 10)
|
|
57
|
+
source: Collection source ("app" or "api") for data isolation. Sent as X-Hebbrix-Source header.
|
|
56
58
|
"""
|
|
57
59
|
|
|
58
60
|
def __init__(
|
|
@@ -66,12 +68,14 @@ class MemoryChat:
|
|
|
66
68
|
learning: bool = True,
|
|
67
69
|
prompt_strategy: str = "default",
|
|
68
70
|
memory_limit: int = 10,
|
|
71
|
+
source: Optional[str] = None,
|
|
69
72
|
):
|
|
70
73
|
self.api_key = api_key
|
|
71
74
|
self.base_url = base_url.rstrip("/")
|
|
72
75
|
self.model = model
|
|
73
76
|
self.prompt_strategy = prompt_strategy
|
|
74
77
|
self.memory_limit = memory_limit
|
|
78
|
+
self.source = source
|
|
75
79
|
|
|
76
80
|
# Feature configuration
|
|
77
81
|
self.features = {
|
|
@@ -82,7 +86,7 @@ class MemoryChat:
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
# Also create full client for advanced operations
|
|
85
|
-
self.client = MemoryClient(api_key=api_key, base_url=base_url)
|
|
89
|
+
self.client = MemoryClient(api_key=api_key, base_url=base_url, source=source)
|
|
86
90
|
|
|
87
91
|
def send(
|
|
88
92
|
self,
|
|
@@ -127,6 +131,8 @@ class MemoryChat:
|
|
|
127
131
|
"Authorization": f"Bearer {self.api_key}",
|
|
128
132
|
"Content-Type": "application/json",
|
|
129
133
|
}
|
|
134
|
+
if self.source:
|
|
135
|
+
headers["X-Hebbrix-Source"] = self.source
|
|
130
136
|
|
|
131
137
|
response = requests.post(url, json=payload, headers=headers)
|
|
132
138
|
response.raise_for_status()
|
|
@@ -179,6 +185,8 @@ class MemoryChat:
|
|
|
179
185
|
"Authorization": f"Bearer {self.api_key}",
|
|
180
186
|
"Content-Type": "application/json",
|
|
181
187
|
}
|
|
188
|
+
if self.source:
|
|
189
|
+
headers["X-Hebbrix-Source"] = self.source
|
|
182
190
|
|
|
183
191
|
response = requests.post(url, json=payload, headers=headers)
|
|
184
192
|
response.raise_for_status()
|
|
@@ -288,7 +296,9 @@ class MemoryChat:
|
|
|
288
296
|
# Convenience methods for memory operations
|
|
289
297
|
# These use synchronous requests.post() (same as send/send_with_context)
|
|
290
298
|
# instead of the async MemoryClient to avoid coroutine issues.
|
|
291
|
-
def add_memory(
|
|
299
|
+
def add_memory(
|
|
300
|
+
self, content: str, collection_id: str, importance: float = 0.5
|
|
301
|
+
) -> Dict[str, Any]:
|
|
292
302
|
"""
|
|
293
303
|
Add a memory manually.
|
|
294
304
|
|
|
@@ -315,7 +325,9 @@ class MemoryChat:
|
|
|
315
325
|
response.raise_for_status()
|
|
316
326
|
return response.json()
|
|
317
327
|
|
|
318
|
-
def search_memories(
|
|
328
|
+
def search_memories(
|
|
329
|
+
self, query: str, collection_id: Optional[str] = None, limit: int = 10
|
|
330
|
+
) -> List[Dict[str, Any]]:
|
|
319
331
|
"""
|
|
320
332
|
Search memories manually.
|
|
321
333
|
|
|
@@ -3,30 +3,19 @@ Hebbrix Client
|
|
|
3
3
|
|
|
4
4
|
Main client class for interacting with the Hebbrix api.
|
|
5
5
|
"""
|
|
6
|
-
from typing import Optional, Dict, Any, List
|
|
7
|
-
import httpx
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
22
|
-
from hebbrix.exceptions import (
|
|
23
|
-
HebbrixError,
|
|
24
|
-
AuthenticationError,
|
|
25
|
-
ValidationError,
|
|
26
|
-
NotFoundError,
|
|
27
|
-
RateLimitError,
|
|
28
|
-
ServerError,
|
|
29
|
-
)
|
|
7
|
+
import os
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
from hebbrix.exceptions import (AuthenticationError, HebbrixError,
|
|
12
|
+
NotFoundError, RateLimitError, ServerError,
|
|
13
|
+
ValidationError)
|
|
14
|
+
from hebbrix.resources import (AuthResource, CollectionsResource,
|
|
15
|
+
ConsolidationResource, MemoriesResource,
|
|
16
|
+
MemoryToolsResource, ProceduralResource,
|
|
17
|
+
RLResource, SearchResource, TemporalResource,
|
|
18
|
+
WorkingMemoryResource, WorldModelResource)
|
|
30
19
|
|
|
31
20
|
|
|
32
21
|
class MemoryClient:
|
|
@@ -37,6 +26,7 @@ class MemoryClient:
|
|
|
37
26
|
api_key: API key for authentication
|
|
38
27
|
base_url: Base URL of the API (default: https://api.hebbrix.com)
|
|
39
28
|
timeout: Request timeout in seconds (default: 30)
|
|
29
|
+
source: Collection source ("app" or "api") for data isolation. Falls back to HEBBRIX_SOURCE env var.
|
|
40
30
|
|
|
41
31
|
Example:
|
|
42
32
|
>>> client = MemoryClient(api_key="mem_sk_...")
|
|
@@ -51,10 +41,12 @@ class MemoryClient:
|
|
|
51
41
|
api_key: Optional[str] = None,
|
|
52
42
|
base_url: str = "https://api.hebbrix.com",
|
|
53
43
|
timeout: float = 120.0,
|
|
44
|
+
source: Optional[str] = None,
|
|
54
45
|
):
|
|
55
46
|
self.api_key = api_key
|
|
56
47
|
self.base_url = base_url.rstrip("/")
|
|
57
48
|
self.timeout = timeout
|
|
49
|
+
self.source = source or os.getenv("HEBBRIX_SOURCE")
|
|
58
50
|
|
|
59
51
|
# HTTP client
|
|
60
52
|
self._client = httpx.AsyncClient(
|
|
@@ -86,6 +78,9 @@ class MemoryClient:
|
|
|
86
78
|
if self.api_key:
|
|
87
79
|
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
88
80
|
|
|
81
|
+
if self.source:
|
|
82
|
+
headers["X-Hebbrix-Source"] = self.source
|
|
83
|
+
|
|
89
84
|
return headers
|
|
90
85
|
|
|
91
86
|
def _handle_error(self, response: httpx.Response) -> None:
|
|
@@ -3,7 +3,7 @@ API Resource classes
|
|
|
3
3
|
|
|
4
4
|
Each resource class wraps a specific set of API endpoints.
|
|
5
5
|
"""
|
|
6
|
-
from typing import Optional, Dict, Any, List, TYPE_CHECKING
|
|
6
|
+
from typing import Optional, Dict, Any, List, AsyncIterator, TYPE_CHECKING
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from hebbrix.client import MemoryClient
|
|
@@ -227,29 +227,94 @@ class MemoriesResource(BaseResource):
|
|
|
227
227
|
},
|
|
228
228
|
)
|
|
229
229
|
|
|
230
|
-
async def
|
|
230
|
+
async def list_page(
|
|
231
231
|
self,
|
|
232
232
|
collection_id: Optional[str] = None,
|
|
233
|
-
|
|
234
|
-
limit: int =
|
|
235
|
-
) ->
|
|
233
|
+
cursor: Optional[str] = None,
|
|
234
|
+
limit: int = 50,
|
|
235
|
+
) -> Dict[str, Any]:
|
|
236
236
|
"""
|
|
237
|
-
List memories.
|
|
237
|
+
List memories with full pagination metadata.
|
|
238
|
+
|
|
239
|
+
Returns the raw cursor-paginated response from the backend so callers
|
|
240
|
+
can iterate pages explicitly.
|
|
238
241
|
|
|
239
242
|
Args:
|
|
240
243
|
collection_id: Optional collection filter
|
|
241
|
-
|
|
242
|
-
limit:
|
|
244
|
+
cursor: Opaque cursor from a previous page (None for the first page)
|
|
245
|
+
limit: Page size (backend max: 100)
|
|
243
246
|
|
|
244
247
|
Returns:
|
|
245
|
-
|
|
248
|
+
Dict with keys:
|
|
249
|
+
- items: List[Dict[str, Any]] — memories in this page
|
|
250
|
+
- next_cursor: Optional[str] — pass to the next call to continue
|
|
251
|
+
- has_more: bool — True if more pages exist
|
|
252
|
+
- total_count: int — total number of memories matching the filter
|
|
246
253
|
"""
|
|
247
|
-
params = {"
|
|
254
|
+
params: Dict[str, Any] = {"limit": limit}
|
|
248
255
|
if collection_id:
|
|
249
256
|
params["collection_id"] = collection_id
|
|
257
|
+
if cursor:
|
|
258
|
+
params["cursor"] = cursor
|
|
250
259
|
|
|
251
260
|
return await self.client.get("/v1/memories", params=params)
|
|
252
261
|
|
|
262
|
+
async def list(
|
|
263
|
+
self,
|
|
264
|
+
collection_id: Optional[str] = None,
|
|
265
|
+
cursor: Optional[str] = None,
|
|
266
|
+
limit: int = 50,
|
|
267
|
+
) -> List[Dict[str, Any]]:
|
|
268
|
+
"""
|
|
269
|
+
List memories (single page, items only).
|
|
270
|
+
|
|
271
|
+
Back-compat convenience that drops pagination metadata. For
|
|
272
|
+
page-at-a-time access use `list_page`; for iteration across all
|
|
273
|
+
pages use `iter_all`.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
collection_id: Optional collection filter
|
|
277
|
+
cursor: Opaque cursor from a previous page
|
|
278
|
+
limit: Page size (backend max: 100)
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
List of memory dicts for the requested page
|
|
282
|
+
"""
|
|
283
|
+
page = await self.list_page(
|
|
284
|
+
collection_id=collection_id, cursor=cursor, limit=limit
|
|
285
|
+
)
|
|
286
|
+
return page.get("items", [])
|
|
287
|
+
|
|
288
|
+
async def iter_all(
|
|
289
|
+
self,
|
|
290
|
+
collection_id: Optional[str] = None,
|
|
291
|
+
limit: int = 50,
|
|
292
|
+
) -> AsyncIterator[Dict[str, Any]]:
|
|
293
|
+
"""
|
|
294
|
+
Async-iterate every memory matching the filter, following cursors.
|
|
295
|
+
|
|
296
|
+
Example:
|
|
297
|
+
async for memory in client.memories.iter_all(collection_id="col_x"):
|
|
298
|
+
print(memory["id"])
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
collection_id: Optional collection filter
|
|
302
|
+
limit: Page size used under the hood (backend max: 100)
|
|
303
|
+
|
|
304
|
+
Yields:
|
|
305
|
+
Memory dicts, one per item, across all pages
|
|
306
|
+
"""
|
|
307
|
+
cursor: Optional[str] = None
|
|
308
|
+
while True:
|
|
309
|
+
page = await self.list_page(
|
|
310
|
+
collection_id=collection_id, cursor=cursor, limit=limit
|
|
311
|
+
)
|
|
312
|
+
for item in page.get("items", []):
|
|
313
|
+
yield item
|
|
314
|
+
if not page.get("has_more") or not page.get("next_cursor"):
|
|
315
|
+
break
|
|
316
|
+
cursor = page["next_cursor"]
|
|
317
|
+
|
|
253
318
|
async def get(self, memory_id: str) -> Dict[str, Any]:
|
|
254
319
|
"""
|
|
255
320
|
Get a specific memory.
|
|
@@ -9,7 +9,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="hebbrix",
|
|
12
|
-
version="2.0.
|
|
12
|
+
version="2.0.3",
|
|
13
13
|
author="Hebbrix Team",
|
|
14
14
|
author_email="support@hebbrix.com",
|
|
15
15
|
description="Advanced Memory API for AI Agents with Reinforcement Learning - 3-line integration",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|