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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hebbrix
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: Advanced Memory API for AI Agents with Reinforcement Learning - 3-line integration
5
5
  Home-page: https://github.com/hebbrix/hebbrix-python
6
6
  Author: Hebbrix Team
@@ -41,7 +41,7 @@ Features:
41
41
  - ✅ Type hints throughout
42
42
  """
43
43
 
44
- __version__ = "2.0.2"
44
+ __version__ = "2.0.3"
45
45
  __author__ = "Hebbrix Team"
46
46
  __license__ = "MIT"
47
47
 
@@ -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(self, content: str, collection_id: str, importance: float = 0.5) -> Dict[str, Any]:
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(self, query: str, collection_id: Optional[str] = None, limit: int = 10) -> List[Dict[str, Any]]:
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
- from hebbrix.resources import (
10
- AuthResource,
11
- CollectionsResource,
12
- MemoriesResource,
13
- SearchResource,
14
- RLResource,
15
- ProceduralResource,
16
- TemporalResource,
17
- WorkingMemoryResource,
18
- ConsolidationResource,
19
- MemoryToolsResource,
20
- WorldModelResource,
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 list(
230
+ async def list_page(
231
231
  self,
232
232
  collection_id: Optional[str] = None,
233
- skip: int = 0,
234
- limit: int = 100,
235
- ) -> List[Dict[str, Any]]:
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
- skip: Number of items to skip
242
- limit: Maximum number of items
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
- List of memories
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 = {"skip": skip, "limit": limit}
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hebbrix
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: Advanced Memory API for AI Agents with Reinforcement Learning - 3-line integration
5
5
  Home-page: https://github.com/hebbrix/hebbrix-python
6
6
  Author: Hebbrix Team
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hebbrix"
7
- version = "2.0.2"
7
+ version = "2.0.3"
8
8
  description = "Advanced Memory API for AI Agents with Reinforcement Learning - 3-line integration"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -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.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