hebbrix 2.3.2__tar.gz → 2.4.0__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.3.2 → hebbrix-2.4.0}/CHANGELOG.md +14 -0
- hebbrix-2.4.0/PKG-INFO +139 -0
- hebbrix-2.4.0/README.md +98 -0
- hebbrix-2.4.0/hebbrix/__init__.py +42 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix/client.py +58 -11
- hebbrix-2.4.0/hebbrix/exceptions.py +76 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix/resources.py +157 -140
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix/sync_client.py +67 -17
- hebbrix-2.4.0/hebbrix.egg-info/PKG-INFO +139 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix.egg-info/SOURCES.txt +1 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/pyproject.toml +7 -6
- hebbrix-2.4.0/tests/test_advanced_resources.py +96 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/tests/test_openapi_parity.py +76 -0
- hebbrix-2.3.2/PKG-INFO +0 -205
- hebbrix-2.3.2/README.md +0 -143
- hebbrix-2.3.2/hebbrix/__init__.py +0 -74
- hebbrix-2.3.2/hebbrix/exceptions.py +0 -48
- hebbrix-2.3.2/hebbrix.egg-info/PKG-INFO +0 -205
- {hebbrix-2.3.2 → hebbrix-2.4.0}/LICENSE +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/MANIFEST.in +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix/chat.py +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix/models.py +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix.egg-info/dependency_links.txt +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix.egg-info/requires.txt +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/hebbrix.egg-info/top_level.txt +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/setup.cfg +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/tests/test_memories_resource.py +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/tests/test_procedural_resource.py +0 -0
- {hebbrix-2.3.2 → hebbrix-2.4.0}/tests/test_sync_client.py +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.4.0 — 2026-08-27
|
|
4
|
+
|
|
5
|
+
- Reconcile every exported advanced method with the canonical public OpenAPI,
|
|
6
|
+
including temporal, working-memory, consolidation, memory-tool, and RL routes.
|
|
7
|
+
- Add a route-manifest release gate and clean-wheel installation verification.
|
|
8
|
+
- Treat durable-but-indexing batch results as `202`, poll them through the SDK,
|
|
9
|
+
and raise `IndexingTimeoutError` with the durable receipt on client deadline.
|
|
10
|
+
- Preserve structured entitlement metadata in `EntitlementError`.
|
|
11
|
+
- Keep advanced resources async-only and document the sync-client boundary.
|
|
12
|
+
- Withdraw the experimental World Model from the public SDK until a trained,
|
|
13
|
+
versioned production model artifact and serving contract exist.
|
|
14
|
+
- Publish compatibility through `GET /v1/release`; replace the broken public
|
|
15
|
+
repository link with valid artifact and support links.
|
|
16
|
+
|
|
3
17
|
## 2.3.2 — 2026-08-27
|
|
4
18
|
|
|
5
19
|
- Align procedure create/list/get/update/execute/delete with the canonical
|
hebbrix-2.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hebbrix
|
|
3
|
+
Version: 2.4.0
|
|
4
|
+
Summary: Typed Python client for Hebbrix memory, retrieval, and outcome-learning APIs
|
|
5
|
+
Author-email: Hebbrix Team <support@hebbrix.com>
|
|
6
|
+
Maintainer-email: Hebbrix Team <support@hebbrix.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://hebbrix.com
|
|
9
|
+
Project-URL: Documentation, https://docs.hebbrix.com
|
|
10
|
+
Project-URL: Source, https://pypi.org/project/hebbrix/#files
|
|
11
|
+
Project-URL: Support, https://www.hebbrix.com/contact
|
|
12
|
+
Project-URL: API Reference, https://api.hebbrix.com/docs
|
|
13
|
+
Keywords: ai,memory,agents,llm,chatbot,assistant,ml,reinforcement-learning,knowledge-graph,vector-search,rag,temporal,procedural-memory,working-memory
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Topic :: Database
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Operating System :: OS Independent
|
|
26
|
+
Classifier: Framework :: AsyncIO
|
|
27
|
+
Requires-Python: >=3.8
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: httpx>=0.25.0
|
|
31
|
+
Requires-Dist: requests>=2.31.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: flake8<6.0.0,>=5.0.4; python_full_version < "3.8.1" and extra == "dev"
|
|
37
|
+
Requires-Dist: flake8>=6.0.0; python_full_version >= "3.8.1" and extra == "dev"
|
|
38
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: cryptography>=42.0.0; extra == "dev"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
# Hebbrix Python SDK
|
|
43
|
+
|
|
44
|
+
Typed Python client for Hebbrix memory, retrieval, and outcome-learning APIs.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install hebbrix==2.4.0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Python 3.8+ is supported. `MemoryClient` is asynchronous. `SyncMemoryClient`
|
|
53
|
+
supports the core collection, memory, search, correction, procedure, and
|
|
54
|
+
ProofLoop workflows; advanced temporal, working-memory, consolidation,
|
|
55
|
+
memory-tool, and RL resources are currently async-only.
|
|
56
|
+
|
|
57
|
+
## Quick start
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import asyncio
|
|
61
|
+
from hebbrix import MemoryClient
|
|
62
|
+
|
|
63
|
+
async def main():
|
|
64
|
+
async with MemoryClient(api_key="hbx_your_api_key") as client:
|
|
65
|
+
collection = await client.collections.create(name="Support memory")
|
|
66
|
+
memory = await client.memories.create(
|
|
67
|
+
collection_id=collection["id"],
|
|
68
|
+
content="Customer prefers concise replies",
|
|
69
|
+
wait_for_index=True,
|
|
70
|
+
idempotency_key="customer-42-preference-v1",
|
|
71
|
+
)
|
|
72
|
+
results = await client.search(
|
|
73
|
+
"How should replies be formatted?",
|
|
74
|
+
collection_id=collection["id"],
|
|
75
|
+
)
|
|
76
|
+
print(memory, results)
|
|
77
|
+
|
|
78
|
+
asyncio.run(main())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Durable readiness
|
|
82
|
+
|
|
83
|
+
Memory writes return either a searchable completion or a durable `202` receipt.
|
|
84
|
+
A durable receipt means the database commit succeeded while indexing is still
|
|
85
|
+
converging; it is not a failure and does not justify a duplicate write.
|
|
86
|
+
|
|
87
|
+
When `wait_for_index=True`, the SDK accepts that receipt and polls the documented
|
|
88
|
+
status URL. It returns only after `searchable=true`. If the caller's deadline
|
|
89
|
+
expires, it raises `IndexingTimeoutError`; the exception retains the original
|
|
90
|
+
receipt, durable memory IDs, and status URL. Reuse the same idempotency key with
|
|
91
|
+
the same body to recover the same logical resources.
|
|
92
|
+
|
|
93
|
+
For an asynchronous batch receipt:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
receipt = await client.memories.create_batch(
|
|
97
|
+
[{"content": "First fact"}, {"content": "Second fact"}],
|
|
98
|
+
collection_id="collection-42",
|
|
99
|
+
wait_for_index=False,
|
|
100
|
+
idempotency_key="import-42",
|
|
101
|
+
)
|
|
102
|
+
completed = await client.memories.wait_batch_until_searchable(receipt)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Pagination
|
|
106
|
+
|
|
107
|
+
`collections.list()` returns the current page's collection items for backward
|
|
108
|
+
compatibility. Use `collections.list_page()` when cursor metadata is required.
|
|
109
|
+
Memory resources provide the same `list()`/`list_page()` distinction.
|
|
110
|
+
|
|
111
|
+
## Advanced capabilities and entitlements
|
|
112
|
+
|
|
113
|
+
The async client exposes the canonical `/v1` temporal, working-memory,
|
|
114
|
+
consolidation, memory-tool, and RL contracts. RL metrics and evaluation require
|
|
115
|
+
the Pro plan. Process-wide RL training and checkpoint mutation require an admin
|
|
116
|
+
role. Entitlement failures raise `EntitlementError` and preserve the stable
|
|
117
|
+
error code, current/required plan, request ID, and support action.
|
|
118
|
+
|
|
119
|
+
The experimental World Model is intentionally not exported by this public SDK.
|
|
120
|
+
It remains withdrawn until a trained, versioned production model artifact and
|
|
121
|
+
an end-to-end public serving contract are available.
|
|
122
|
+
|
|
123
|
+
The authoritative account capability matrix is available from
|
|
124
|
+
`GET /v1/users/me/capabilities`.
|
|
125
|
+
|
|
126
|
+
## Release compatibility
|
|
127
|
+
|
|
128
|
+
The production API publishes exact build and artifact compatibility at
|
|
129
|
+
[`GET /v1/release`](https://api.hebbrix.com/v1/release). The public OpenAPI is
|
|
130
|
+
[`/openapi.json`](https://api.hebbrix.com/openapi.json).
|
|
131
|
+
|
|
132
|
+
- [Documentation](https://docs.hebbrix.com)
|
|
133
|
+
- [API reference](https://api.hebbrix.com/docs)
|
|
134
|
+
- [PyPI files](https://pypi.org/project/hebbrix/#files)
|
|
135
|
+
- [Support](https://www.hebbrix.com/contact)
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT. See `LICENSE` in the distribution.
|
hebbrix-2.4.0/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Hebbrix Python SDK
|
|
2
|
+
|
|
3
|
+
Typed Python client for Hebbrix memory, retrieval, and outcome-learning APIs.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install hebbrix==2.4.0
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Python 3.8+ is supported. `MemoryClient` is asynchronous. `SyncMemoryClient`
|
|
12
|
+
supports the core collection, memory, search, correction, procedure, and
|
|
13
|
+
ProofLoop workflows; advanced temporal, working-memory, consolidation,
|
|
14
|
+
memory-tool, and RL resources are currently async-only.
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import asyncio
|
|
20
|
+
from hebbrix import MemoryClient
|
|
21
|
+
|
|
22
|
+
async def main():
|
|
23
|
+
async with MemoryClient(api_key="hbx_your_api_key") as client:
|
|
24
|
+
collection = await client.collections.create(name="Support memory")
|
|
25
|
+
memory = await client.memories.create(
|
|
26
|
+
collection_id=collection["id"],
|
|
27
|
+
content="Customer prefers concise replies",
|
|
28
|
+
wait_for_index=True,
|
|
29
|
+
idempotency_key="customer-42-preference-v1",
|
|
30
|
+
)
|
|
31
|
+
results = await client.search(
|
|
32
|
+
"How should replies be formatted?",
|
|
33
|
+
collection_id=collection["id"],
|
|
34
|
+
)
|
|
35
|
+
print(memory, results)
|
|
36
|
+
|
|
37
|
+
asyncio.run(main())
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Durable readiness
|
|
41
|
+
|
|
42
|
+
Memory writes return either a searchable completion or a durable `202` receipt.
|
|
43
|
+
A durable receipt means the database commit succeeded while indexing is still
|
|
44
|
+
converging; it is not a failure and does not justify a duplicate write.
|
|
45
|
+
|
|
46
|
+
When `wait_for_index=True`, the SDK accepts that receipt and polls the documented
|
|
47
|
+
status URL. It returns only after `searchable=true`. If the caller's deadline
|
|
48
|
+
expires, it raises `IndexingTimeoutError`; the exception retains the original
|
|
49
|
+
receipt, durable memory IDs, and status URL. Reuse the same idempotency key with
|
|
50
|
+
the same body to recover the same logical resources.
|
|
51
|
+
|
|
52
|
+
For an asynchronous batch receipt:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
receipt = await client.memories.create_batch(
|
|
56
|
+
[{"content": "First fact"}, {"content": "Second fact"}],
|
|
57
|
+
collection_id="collection-42",
|
|
58
|
+
wait_for_index=False,
|
|
59
|
+
idempotency_key="import-42",
|
|
60
|
+
)
|
|
61
|
+
completed = await client.memories.wait_batch_until_searchable(receipt)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Pagination
|
|
65
|
+
|
|
66
|
+
`collections.list()` returns the current page's collection items for backward
|
|
67
|
+
compatibility. Use `collections.list_page()` when cursor metadata is required.
|
|
68
|
+
Memory resources provide the same `list()`/`list_page()` distinction.
|
|
69
|
+
|
|
70
|
+
## Advanced capabilities and entitlements
|
|
71
|
+
|
|
72
|
+
The async client exposes the canonical `/v1` temporal, working-memory,
|
|
73
|
+
consolidation, memory-tool, and RL contracts. RL metrics and evaluation require
|
|
74
|
+
the Pro plan. Process-wide RL training and checkpoint mutation require an admin
|
|
75
|
+
role. Entitlement failures raise `EntitlementError` and preserve the stable
|
|
76
|
+
error code, current/required plan, request ID, and support action.
|
|
77
|
+
|
|
78
|
+
The experimental World Model is intentionally not exported by this public SDK.
|
|
79
|
+
It remains withdrawn until a trained, versioned production model artifact and
|
|
80
|
+
an end-to-end public serving contract are available.
|
|
81
|
+
|
|
82
|
+
The authoritative account capability matrix is available from
|
|
83
|
+
`GET /v1/users/me/capabilities`.
|
|
84
|
+
|
|
85
|
+
## Release compatibility
|
|
86
|
+
|
|
87
|
+
The production API publishes exact build and artifact compatibility at
|
|
88
|
+
[`GET /v1/release`](https://api.hebbrix.com/v1/release). The public OpenAPI is
|
|
89
|
+
[`/openapi.json`](https://api.hebbrix.com/openapi.json).
|
|
90
|
+
|
|
91
|
+
- [Documentation](https://docs.hebbrix.com)
|
|
92
|
+
- [API reference](https://api.hebbrix.com/docs)
|
|
93
|
+
- [PyPI files](https://pypi.org/project/hebbrix/#files)
|
|
94
|
+
- [Support](https://www.hebbrix.com/contact)
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT. See `LICENSE` in the distribution.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Typed async-first client for Hebbrix memory and outcome-learning APIs.
|
|
2
|
+
|
|
3
|
+
The public surface and its plan/role restrictions are documented by the
|
|
4
|
+
production OpenAPI and ``GET /v1/users/me/capabilities``. The experimental
|
|
5
|
+
World Model is intentionally absent from this release.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "2.4.0"
|
|
9
|
+
__author__ = "Hebbrix Team"
|
|
10
|
+
__license__ = "MIT"
|
|
11
|
+
|
|
12
|
+
from hebbrix.chat import MemoryChat
|
|
13
|
+
from hebbrix.client import MemoryClient
|
|
14
|
+
from hebbrix.exceptions import (
|
|
15
|
+
AuthenticationError,
|
|
16
|
+
EntitlementError,
|
|
17
|
+
HebbrixError,
|
|
18
|
+
IndexingTimeoutError,
|
|
19
|
+
NotFoundError,
|
|
20
|
+
RateLimitError,
|
|
21
|
+
ServerError,
|
|
22
|
+
ValidationError,
|
|
23
|
+
)
|
|
24
|
+
from hebbrix.models import EvidenceClaim, GroundingReceipt, SearchSafetyEnvelope
|
|
25
|
+
from hebbrix.sync_client import SyncMemoryClient
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"MemoryClient",
|
|
29
|
+
"SyncMemoryClient",
|
|
30
|
+
"MemoryChat",
|
|
31
|
+
"HebbrixError",
|
|
32
|
+
"AuthenticationError",
|
|
33
|
+
"EntitlementError",
|
|
34
|
+
"IndexingTimeoutError",
|
|
35
|
+
"ValidationError",
|
|
36
|
+
"NotFoundError",
|
|
37
|
+
"RateLimitError",
|
|
38
|
+
"ServerError",
|
|
39
|
+
"GroundingReceipt",
|
|
40
|
+
"EvidenceClaim",
|
|
41
|
+
"SearchSafetyEnvelope",
|
|
42
|
+
]
|
|
@@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional
|
|
|
10
10
|
import httpx
|
|
11
11
|
from hebbrix.exceptions import (
|
|
12
12
|
AuthenticationError,
|
|
13
|
+
EntitlementError,
|
|
13
14
|
HebbrixError,
|
|
14
15
|
NotFoundError,
|
|
15
16
|
RateLimitError,
|
|
@@ -30,7 +31,6 @@ from hebbrix.resources import (
|
|
|
30
31
|
SearchResource,
|
|
31
32
|
TemporalResource,
|
|
32
33
|
WorkingMemoryResource,
|
|
33
|
-
WorldModelResource,
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
|
|
@@ -85,13 +85,12 @@ class MemoryClient:
|
|
|
85
85
|
self.working_memory = WorkingMemoryResource(self)
|
|
86
86
|
self.consolidation = ConsolidationResource(self)
|
|
87
87
|
self.memory_tools = MemoryToolsResource(self)
|
|
88
|
-
self.world_model = WorldModelResource(self)
|
|
89
88
|
|
|
90
89
|
def _get_headers(self) -> Dict[str, str]:
|
|
91
90
|
"""Get request headers."""
|
|
92
91
|
headers = {
|
|
93
92
|
"Content-Type": "application/json",
|
|
94
|
-
"User-Agent": "hebbrix-python/2.
|
|
93
|
+
"User-Agent": "hebbrix-python/2.4.0",
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
if self.api_key:
|
|
@@ -108,23 +107,71 @@ class MemoryClient:
|
|
|
108
107
|
|
|
109
108
|
try:
|
|
110
109
|
error_data = response.json()
|
|
111
|
-
message = error_data.get("error", {}).get("message", response.text)
|
|
112
110
|
except Exception:
|
|
113
|
-
|
|
111
|
+
error_data = {}
|
|
112
|
+
|
|
113
|
+
envelope = error_data.get("error") or error_data.get("detail") or {}
|
|
114
|
+
if not isinstance(envelope, dict):
|
|
115
|
+
envelope = {"message": str(envelope)}
|
|
116
|
+
nested = envelope.get("message")
|
|
117
|
+
details = nested if isinstance(nested, dict) else envelope
|
|
118
|
+
message = (
|
|
119
|
+
(details.get("message") if isinstance(details, dict) else None)
|
|
120
|
+
or (nested if isinstance(nested, str) else None)
|
|
121
|
+
or response.text
|
|
122
|
+
)
|
|
123
|
+
code = str(details.get("code") or envelope.get("code") or "") or None
|
|
124
|
+
request_id = (
|
|
125
|
+
details.get("request_id")
|
|
126
|
+
or envelope.get("request_id")
|
|
127
|
+
or response.headers.get("X-Request-ID")
|
|
128
|
+
)
|
|
114
129
|
|
|
115
130
|
if status_code == 401:
|
|
116
|
-
raise AuthenticationError(
|
|
131
|
+
raise AuthenticationError(
|
|
132
|
+
message, code=code, request_id=request_id, details=details
|
|
133
|
+
)
|
|
117
134
|
elif status_code == 404:
|
|
118
|
-
raise NotFoundError(
|
|
135
|
+
raise NotFoundError(
|
|
136
|
+
message, code=code, request_id=request_id, details=details
|
|
137
|
+
)
|
|
119
138
|
elif status_code == 422:
|
|
120
139
|
errors = error_data.get("error", {}).get("details", [])
|
|
121
|
-
raise ValidationError(
|
|
140
|
+
raise ValidationError(
|
|
141
|
+
message,
|
|
142
|
+
errors=errors,
|
|
143
|
+
code=code,
|
|
144
|
+
request_id=request_id,
|
|
145
|
+
details=details,
|
|
146
|
+
)
|
|
122
147
|
elif status_code == 429:
|
|
123
|
-
raise RateLimitError(
|
|
148
|
+
raise RateLimitError(
|
|
149
|
+
message, code=code, request_id=request_id, details=details
|
|
150
|
+
)
|
|
124
151
|
elif status_code >= 500:
|
|
125
|
-
raise ServerError(
|
|
152
|
+
raise ServerError(
|
|
153
|
+
message, code=code, request_id=request_id, details=details
|
|
154
|
+
)
|
|
155
|
+
elif status_code in {402, 403} and (
|
|
156
|
+
"ENTITLEMENT" in str(code or "")
|
|
157
|
+
or details.get("error")
|
|
158
|
+
in {"feature_not_available", "tier_upgrade_required"}
|
|
159
|
+
):
|
|
160
|
+
raise EntitlementError(
|
|
161
|
+
message,
|
|
162
|
+
status_code=status_code,
|
|
163
|
+
code=code,
|
|
164
|
+
request_id=request_id,
|
|
165
|
+
details=details,
|
|
166
|
+
)
|
|
126
167
|
else:
|
|
127
|
-
raise HebbrixError(
|
|
168
|
+
raise HebbrixError(
|
|
169
|
+
message,
|
|
170
|
+
status_code=status_code,
|
|
171
|
+
code=code,
|
|
172
|
+
request_id=request_id,
|
|
173
|
+
details=details,
|
|
174
|
+
)
|
|
128
175
|
|
|
129
176
|
async def request(
|
|
130
177
|
self,
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Hebbrix SDK Exceptions
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HebbrixError(Exception):
|
|
7
|
+
"""Base exception for Hebbrix SDK."""
|
|
8
|
+
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
message: str,
|
|
12
|
+
status_code: int = None,
|
|
13
|
+
*,
|
|
14
|
+
code: str = None,
|
|
15
|
+
request_id: str = None,
|
|
16
|
+
details: dict = None,
|
|
17
|
+
):
|
|
18
|
+
self.message = message
|
|
19
|
+
self.status_code = status_code
|
|
20
|
+
self.code = code
|
|
21
|
+
self.request_id = request_id
|
|
22
|
+
self.details = details or {}
|
|
23
|
+
super().__init__(self.message)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class EntitlementError(HebbrixError):
|
|
27
|
+
"""The authenticated account lacks the plan or role for an operation."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, message: str, *, status_code: int, **kwargs):
|
|
30
|
+
super().__init__(message, status_code=status_code, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class IndexingTimeoutError(TimeoutError):
|
|
34
|
+
"""A durable write did not become searchable before the client deadline."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, message: str, receipt: dict):
|
|
37
|
+
self.receipt = dict(receipt)
|
|
38
|
+
self.memory_ids = list(receipt.get("memory_ids") or [])
|
|
39
|
+
self.status_url = receipt.get("status_url")
|
|
40
|
+
super().__init__(message)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AuthenticationError(HebbrixError):
|
|
44
|
+
"""Raised when authentication fails."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, message: str = "Authentication failed", **kwargs):
|
|
47
|
+
super().__init__(message, status_code=401, **kwargs)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ValidationError(HebbrixError):
|
|
51
|
+
"""Raised when request validation fails."""
|
|
52
|
+
|
|
53
|
+
def __init__(self, message: str, errors: list = None, **kwargs):
|
|
54
|
+
self.errors = errors or []
|
|
55
|
+
super().__init__(message, status_code=422, **kwargs)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class NotFoundError(HebbrixError):
|
|
59
|
+
"""Raised when a resource is not found."""
|
|
60
|
+
|
|
61
|
+
def __init__(self, message: str = "Resource not found", **kwargs):
|
|
62
|
+
super().__init__(message, status_code=404, **kwargs)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class RateLimitError(HebbrixError):
|
|
66
|
+
"""Raised when rate limit is exceeded."""
|
|
67
|
+
|
|
68
|
+
def __init__(self, message: str = "Rate limit exceeded", **kwargs):
|
|
69
|
+
super().__init__(message, status_code=429, **kwargs)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ServerError(HebbrixError):
|
|
73
|
+
"""Raised when server returns 5xx error."""
|
|
74
|
+
|
|
75
|
+
def __init__(self, message: str = "Internal server error", **kwargs):
|
|
76
|
+
super().__init__(message, status_code=500, **kwargs)
|