agledger 2.0.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.
- agledger-2.0.0/LICENSE +34 -0
- agledger-2.0.0/PKG-INFO +44 -0
- agledger-2.0.0/README.md +18 -0
- agledger-2.0.0/pyproject.toml +45 -0
- agledger-2.0.0/src/agledger/__init__.py +85 -0
- agledger-2.0.0/src/agledger/_client.py +163 -0
- agledger-2.0.0/src/agledger/_errors.py +132 -0
- agledger-2.0.0/src/agledger/_http.py +331 -0
- agledger-2.0.0/src/agledger/py.typed +0 -0
- agledger-2.0.0/src/agledger/resources/__init__.py +37 -0
- agledger-2.0.0/src/agledger/resources/a2a.py +30 -0
- agledger-2.0.0/src/agledger/resources/admin.py +41 -0
- agledger-2.0.0/src/agledger/resources/capabilities.py +29 -0
- agledger-2.0.0/src/agledger/resources/compliance.py +35 -0
- agledger-2.0.0/src/agledger/resources/dashboard.py +30 -0
- agledger-2.0.0/src/agledger/resources/disputes.py +54 -0
- agledger-2.0.0/src/agledger/resources/enterprises.py +46 -0
- agledger-2.0.0/src/agledger/resources/events.py +48 -0
- agledger-2.0.0/src/agledger/resources/health.py +21 -0
- agledger-2.0.0/src/agledger/resources/mandates.py +263 -0
- agledger-2.0.0/src/agledger/resources/notarize.py +57 -0
- agledger-2.0.0/src/agledger/resources/receipts.py +69 -0
- agledger-2.0.0/src/agledger/resources/registration.py +34 -0
- agledger-2.0.0/src/agledger/resources/reputation.py +24 -0
- agledger-2.0.0/src/agledger/resources/schemas.py +29 -0
- agledger-2.0.0/src/agledger/resources/verification.py +30 -0
- agledger-2.0.0/src/agledger/resources/webhooks.py +44 -0
- agledger-2.0.0/src/agledger/types.py +403 -0
- agledger-2.0.0/src/agledger/webhooks/__init__.py +7 -0
- agledger-2.0.0/src/agledger/webhooks/verify.py +95 -0
- agledger-2.0.0/tests/__init__.py +0 -0
- agledger-2.0.0/tests/test_client.py +244 -0
- agledger-2.0.0/tests/test_errors.py +115 -0
- agledger-2.0.0/tests/test_pagination.py +51 -0
- agledger-2.0.0/tests/test_retry.py +115 -0
- agledger-2.0.0/tests/test_webhooks.py +58 -0
agledger-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Copyright (c) 2026 AGLedger LLC. All rights reserved.
|
|
2
|
+
|
|
3
|
+
PROPRIETARY SOFTWARE LICENSE
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are the
|
|
6
|
+
proprietary property of AGLedger LLC. The Software is provided for use
|
|
7
|
+
exclusively with the AGLedger API (https://api.agledger.ai).
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted to use the Software solely for the purpose of
|
|
10
|
+
integrating with AGLedger services via the AGLedger API, subject to the
|
|
11
|
+
following conditions:
|
|
12
|
+
|
|
13
|
+
1. You may not copy, modify, merge, publish, distribute, sublicense, or sell
|
|
14
|
+
copies of the Software, except as required to use it with the AGLedger API.
|
|
15
|
+
|
|
16
|
+
2. You may not use the Software to create a competing product or service.
|
|
17
|
+
|
|
18
|
+
3. You may not reverse engineer, decompile, or disassemble the Software,
|
|
19
|
+
except to the extent permitted by applicable law.
|
|
20
|
+
|
|
21
|
+
Use of this SDK is subject to the AGLedger Terms of Service at
|
|
22
|
+
https://agledger.ai/terms.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
27
|
+
AGLEDGER LLC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
28
|
+
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
29
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
AGLedger™ and the Agentic Contract Specification™ are trademarks of
|
|
34
|
+
AGLedger LLC. Patent pending.
|
agledger-2.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agledger
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: AGLedger SDK — Accountability and audit infrastructure for agentic systems.
|
|
5
|
+
Author-email: AGLedger LLC <support@agledger.ai>
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: accountability,agents,agledger,audit,mandates
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Requires-Dist: httpx<1,>=0.25.0
|
|
20
|
+
Requires-Dist: pydantic<3,>=2.0.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: respx>=0.22; extra == 'dev'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# AGLedger Python SDK
|
|
28
|
+
|
|
29
|
+
Accountability and audit infrastructure for agentic systems.
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from agledger import AgledgerClient
|
|
33
|
+
|
|
34
|
+
client = AgledgerClient(api_key="ach_ent_...")
|
|
35
|
+
mandate = client.mandates.create(
|
|
36
|
+
enterpriseId="ent_123",
|
|
37
|
+
contractType="ACH-PROC-v1",
|
|
38
|
+
contractVersion="1",
|
|
39
|
+
platform="internal",
|
|
40
|
+
criteria={"item": "widgets", "maxQuantity": 100},
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
See [agledger.ai](https://agledger.ai) for documentation.
|
agledger-2.0.0/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# AGLedger Python SDK
|
|
2
|
+
|
|
3
|
+
Accountability and audit infrastructure for agentic systems.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from agledger import AgledgerClient
|
|
7
|
+
|
|
8
|
+
client = AgledgerClient(api_key="ach_ent_...")
|
|
9
|
+
mandate = client.mandates.create(
|
|
10
|
+
enterpriseId="ent_123",
|
|
11
|
+
contractType="ACH-PROC-v1",
|
|
12
|
+
contractVersion="1",
|
|
13
|
+
platform="internal",
|
|
14
|
+
criteria={"item": "widgets", "maxQuantity": 100},
|
|
15
|
+
)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
See [agledger.ai](https://agledger.ai) for documentation.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agledger"
|
|
7
|
+
version = "2.0.0"
|
|
8
|
+
description = "AGLedger SDK — Accountability and audit infrastructure for agentic systems."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "LicenseRef-Proprietary"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{ name = "AGLedger LLC", email = "support@agledger.ai" }]
|
|
13
|
+
keywords = ["agledger", "mandates", "accountability", "agents", "audit"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.9",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"httpx>=0.25.0,<1",
|
|
27
|
+
"pydantic>=2.0.0,<3",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
dev = [
|
|
32
|
+
"pytest>=8.0",
|
|
33
|
+
"pytest-asyncio>=0.24",
|
|
34
|
+
"respx>=0.22",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.wheel]
|
|
38
|
+
packages = ["src/agledger"]
|
|
39
|
+
|
|
40
|
+
[tool.pytest.ini_options]
|
|
41
|
+
asyncio_mode = "auto"
|
|
42
|
+
testpaths = ["tests"]
|
|
43
|
+
|
|
44
|
+
[tool.pyright]
|
|
45
|
+
typeCheckingMode = "strict"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AGLedger SDK — Accountability and audit infrastructure for agentic systems.
|
|
3
|
+
|
|
4
|
+
Patent Pending. Copyright 2026 AGLedger LLC. All rights reserved.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from agledger._client import AgledgerClient, AsyncAgledgerClient
|
|
8
|
+
from agledger._errors import (
|
|
9
|
+
AgledgerError,
|
|
10
|
+
APIConnectionError,
|
|
11
|
+
APIError,
|
|
12
|
+
APITimeoutError,
|
|
13
|
+
AuthenticationError,
|
|
14
|
+
BadRequestError,
|
|
15
|
+
NotFoundError,
|
|
16
|
+
PermissionDeniedError,
|
|
17
|
+
RateLimitError,
|
|
18
|
+
UnprocessableError,
|
|
19
|
+
)
|
|
20
|
+
from agledger.types import (
|
|
21
|
+
AccountProfile,
|
|
22
|
+
AuditChain,
|
|
23
|
+
ContractType,
|
|
24
|
+
DashboardSummary,
|
|
25
|
+
Dispute,
|
|
26
|
+
DisputeStatus,
|
|
27
|
+
EnterpriseAgentRecord,
|
|
28
|
+
Event,
|
|
29
|
+
HealthResponse,
|
|
30
|
+
Mandate,
|
|
31
|
+
MandateStatus,
|
|
32
|
+
MandateTransitionAction,
|
|
33
|
+
OperatingMode,
|
|
34
|
+
Page,
|
|
35
|
+
Receipt,
|
|
36
|
+
ReceiptStatus,
|
|
37
|
+
RegisterResult,
|
|
38
|
+
ReputationScore,
|
|
39
|
+
VerificationMode,
|
|
40
|
+
VerificationOutcome,
|
|
41
|
+
VerificationResult,
|
|
42
|
+
Webhook,
|
|
43
|
+
WebhookEventType,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
__version__ = "2.0.0"
|
|
47
|
+
__all__ = [
|
|
48
|
+
"AgledgerClient",
|
|
49
|
+
"AsyncAgledgerClient",
|
|
50
|
+
# Errors
|
|
51
|
+
"AgledgerError",
|
|
52
|
+
"APIError",
|
|
53
|
+
"AuthenticationError",
|
|
54
|
+
"PermissionDeniedError",
|
|
55
|
+
"NotFoundError",
|
|
56
|
+
"BadRequestError",
|
|
57
|
+
"UnprocessableError",
|
|
58
|
+
"RateLimitError",
|
|
59
|
+
"APIConnectionError",
|
|
60
|
+
"APITimeoutError",
|
|
61
|
+
# Types
|
|
62
|
+
"Mandate",
|
|
63
|
+
"MandateStatus",
|
|
64
|
+
"MandateTransitionAction",
|
|
65
|
+
"Receipt",
|
|
66
|
+
"ReceiptStatus",
|
|
67
|
+
"ContractType",
|
|
68
|
+
"OperatingMode",
|
|
69
|
+
"VerificationMode",
|
|
70
|
+
"VerificationOutcome",
|
|
71
|
+
"VerificationResult",
|
|
72
|
+
"Dispute",
|
|
73
|
+
"DisputeStatus",
|
|
74
|
+
"Webhook",
|
|
75
|
+
"WebhookEventType",
|
|
76
|
+
"ReputationScore",
|
|
77
|
+
"Event",
|
|
78
|
+
"AuditChain",
|
|
79
|
+
"DashboardSummary",
|
|
80
|
+
"AccountProfile",
|
|
81
|
+
"RegisterResult",
|
|
82
|
+
"EnterpriseAgentRecord",
|
|
83
|
+
"HealthResponse",
|
|
84
|
+
"Page",
|
|
85
|
+
]
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AGLedger SDK — Client with 18 resource sub-clients.
|
|
3
|
+
Supports context manager protocol for proper connection cleanup.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from types import TracebackType
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
|
|
13
|
+
from agledger._http import (
|
|
14
|
+
AsyncHttpClient,
|
|
15
|
+
HttpClient,
|
|
16
|
+
DEFAULT_BASE_URL,
|
|
17
|
+
DEFAULT_MAX_RETRIES,
|
|
18
|
+
DEFAULT_TIMEOUT,
|
|
19
|
+
_resolve_api_key,
|
|
20
|
+
)
|
|
21
|
+
from agledger.resources.a2a import A2AResource, AsyncA2AResource
|
|
22
|
+
from agledger.resources.admin import AdminResource, AsyncAdminResource
|
|
23
|
+
from agledger.resources.capabilities import AsyncCapabilitiesResource, CapabilitiesResource
|
|
24
|
+
from agledger.resources.compliance import AsyncComplianceResource, ComplianceResource
|
|
25
|
+
from agledger.resources.dashboard import AsyncDashboardResource, DashboardResource
|
|
26
|
+
from agledger.resources.disputes import AsyncDisputesResource, DisputesResource
|
|
27
|
+
from agledger.resources.enterprises import AsyncEnterprisesResource, EnterprisesResource
|
|
28
|
+
from agledger.resources.events import AsyncEventsResource, EventsResource
|
|
29
|
+
from agledger.resources.health import AsyncHealthResource, HealthResource
|
|
30
|
+
from agledger.resources.mandates import AsyncMandatesResource, MandatesResource
|
|
31
|
+
from agledger.resources.notarize import AsyncNotarizeResource, NotarizeResource
|
|
32
|
+
from agledger.resources.receipts import AsyncReceiptsResource, ReceiptsResource
|
|
33
|
+
from agledger.resources.registration import AsyncRegistrationResource, RegistrationResource
|
|
34
|
+
from agledger.resources.reputation import AsyncReputationResource, ReputationResource
|
|
35
|
+
from agledger.resources.schemas import AsyncSchemasResource, SchemasResource
|
|
36
|
+
from agledger.resources.verification import AsyncVerificationResource, VerificationResource
|
|
37
|
+
from agledger.resources.webhooks import AsyncWebhooksResource, WebhooksResource
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class AgledgerClient:
|
|
41
|
+
"""
|
|
42
|
+
Synchronous AGLedger API client with 18 resource sub-clients.
|
|
43
|
+
|
|
44
|
+
Supports context manager for automatic connection cleanup::
|
|
45
|
+
|
|
46
|
+
with AgledgerClient(api_key="ach_ent_...") as client:
|
|
47
|
+
mandate = client.mandates.create(
|
|
48
|
+
enterprise_id="ent_123",
|
|
49
|
+
contract_type="ACH-PROC-v1",
|
|
50
|
+
contract_version="1",
|
|
51
|
+
platform="internal",
|
|
52
|
+
criteria={"item": "widgets"},
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
Or pass ``AGLEDGER_API_KEY`` env var::
|
|
56
|
+
|
|
57
|
+
client = AgledgerClient() # reads from env
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def __init__(
|
|
61
|
+
self,
|
|
62
|
+
api_key: str | None = None,
|
|
63
|
+
*,
|
|
64
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
65
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
66
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
67
|
+
idempotency_key_prefix: str = "",
|
|
68
|
+
http_client: httpx.Client | None = None,
|
|
69
|
+
) -> None:
|
|
70
|
+
resolved_key = _resolve_api_key(api_key)
|
|
71
|
+
self._http = HttpClient(
|
|
72
|
+
api_key=resolved_key,
|
|
73
|
+
base_url=base_url,
|
|
74
|
+
max_retries=max_retries,
|
|
75
|
+
timeout=timeout,
|
|
76
|
+
idempotency_key_prefix=idempotency_key_prefix,
|
|
77
|
+
http_client=http_client,
|
|
78
|
+
)
|
|
79
|
+
self.mandates = MandatesResource(self._http)
|
|
80
|
+
self.receipts = ReceiptsResource(self._http)
|
|
81
|
+
self.verification = VerificationResource(self._http)
|
|
82
|
+
self.disputes = DisputesResource(self._http)
|
|
83
|
+
self.webhooks = WebhooksResource(self._http)
|
|
84
|
+
self.reputation = ReputationResource(self._http)
|
|
85
|
+
self.events = EventsResource(self._http)
|
|
86
|
+
self.schemas = SchemasResource(self._http)
|
|
87
|
+
self.dashboard = DashboardResource(self._http)
|
|
88
|
+
self.compliance = ComplianceResource(self._http)
|
|
89
|
+
self.registration = RegistrationResource(self._http)
|
|
90
|
+
self.health = HealthResource(self._http)
|
|
91
|
+
self.admin = AdminResource(self._http)
|
|
92
|
+
self.a2a = A2AResource(self._http)
|
|
93
|
+
self.capabilities = CapabilitiesResource(self._http)
|
|
94
|
+
self.notarize = NotarizeResource(self._http)
|
|
95
|
+
self.enterprises = EnterprisesResource(self._http)
|
|
96
|
+
|
|
97
|
+
def close(self) -> None:
|
|
98
|
+
"""Close the underlying HTTP connection pool."""
|
|
99
|
+
self._http.close()
|
|
100
|
+
|
|
101
|
+
def __enter__(self) -> AgledgerClient:
|
|
102
|
+
return self
|
|
103
|
+
|
|
104
|
+
def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None) -> None:
|
|
105
|
+
self.close()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class AsyncAgledgerClient:
|
|
109
|
+
"""
|
|
110
|
+
Async AGLedger API client with 18 resource sub-clients.
|
|
111
|
+
|
|
112
|
+
Supports async context manager::
|
|
113
|
+
|
|
114
|
+
async with AsyncAgledgerClient(api_key="ach_ent_...") as client:
|
|
115
|
+
mandate = await client.mandates.get("mnd-123")
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
def __init__(
|
|
119
|
+
self,
|
|
120
|
+
api_key: str | None = None,
|
|
121
|
+
*,
|
|
122
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
123
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
124
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
125
|
+
idempotency_key_prefix: str = "",
|
|
126
|
+
http_client: httpx.AsyncClient | None = None,
|
|
127
|
+
) -> None:
|
|
128
|
+
resolved_key = _resolve_api_key(api_key)
|
|
129
|
+
self._http = AsyncHttpClient(
|
|
130
|
+
api_key=resolved_key,
|
|
131
|
+
base_url=base_url,
|
|
132
|
+
max_retries=max_retries,
|
|
133
|
+
timeout=timeout,
|
|
134
|
+
idempotency_key_prefix=idempotency_key_prefix,
|
|
135
|
+
http_client=http_client,
|
|
136
|
+
)
|
|
137
|
+
self.mandates = AsyncMandatesResource(self._http)
|
|
138
|
+
self.receipts = AsyncReceiptsResource(self._http)
|
|
139
|
+
self.verification = AsyncVerificationResource(self._http)
|
|
140
|
+
self.disputes = AsyncDisputesResource(self._http)
|
|
141
|
+
self.webhooks = AsyncWebhooksResource(self._http)
|
|
142
|
+
self.reputation = AsyncReputationResource(self._http)
|
|
143
|
+
self.events = AsyncEventsResource(self._http)
|
|
144
|
+
self.schemas = AsyncSchemasResource(self._http)
|
|
145
|
+
self.dashboard = AsyncDashboardResource(self._http)
|
|
146
|
+
self.compliance = AsyncComplianceResource(self._http)
|
|
147
|
+
self.registration = AsyncRegistrationResource(self._http)
|
|
148
|
+
self.health = AsyncHealthResource(self._http)
|
|
149
|
+
self.admin = AsyncAdminResource(self._http)
|
|
150
|
+
self.a2a = AsyncA2AResource(self._http)
|
|
151
|
+
self.capabilities = AsyncCapabilitiesResource(self._http)
|
|
152
|
+
self.notarize = AsyncNotarizeResource(self._http)
|
|
153
|
+
self.enterprises = AsyncEnterprisesResource(self._http)
|
|
154
|
+
|
|
155
|
+
async def close(self) -> None:
|
|
156
|
+
"""Close the underlying HTTP connection pool."""
|
|
157
|
+
await self._http.close()
|
|
158
|
+
|
|
159
|
+
async def __aenter__(self) -> AsyncAgledgerClient:
|
|
160
|
+
return self
|
|
161
|
+
|
|
162
|
+
async def __aexit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None) -> None:
|
|
163
|
+
await self.close()
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AGLedger SDK — Error classes.
|
|
3
|
+
Follows Anthropic/OpenAI naming conventions. Never shadows Python builtins.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AgledgerError(Exception):
|
|
12
|
+
"""Base error for all SDK errors."""
|
|
13
|
+
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class APIError(AgledgerError):
|
|
18
|
+
"""API returned an error response."""
|
|
19
|
+
|
|
20
|
+
status: int
|
|
21
|
+
code: str
|
|
22
|
+
request_id: Optional[str]
|
|
23
|
+
details: Optional[Any]
|
|
24
|
+
retryable: bool
|
|
25
|
+
doc_url: str
|
|
26
|
+
|
|
27
|
+
__slots__ = ("status", "code", "request_id", "details", "retryable", "doc_url")
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
status: int,
|
|
32
|
+
*,
|
|
33
|
+
message: str = "",
|
|
34
|
+
code: str = "unknown",
|
|
35
|
+
request_id: Optional[str] = None,
|
|
36
|
+
details: Optional[Any] = None,
|
|
37
|
+
retryable: Optional[bool] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
self.status = status
|
|
40
|
+
self.code = code
|
|
41
|
+
self.request_id = request_id
|
|
42
|
+
self.details = details
|
|
43
|
+
self.retryable = retryable if retryable is not None else (status == 429 or status >= 500)
|
|
44
|
+
self.doc_url = f"https://docs.agledger.ai/errors/{self.code}"
|
|
45
|
+
super().__init__(message or f"API error {status}")
|
|
46
|
+
|
|
47
|
+
def __repr__(self) -> str:
|
|
48
|
+
return f"{self.__class__.__name__}(status={self.status}, code={self.code!r}, message={str(self)!r})"
|
|
49
|
+
|
|
50
|
+
def is_retryable(self) -> bool:
|
|
51
|
+
"""Whether this error can be retried (429, 5xx, network errors)."""
|
|
52
|
+
return self.retryable
|
|
53
|
+
|
|
54
|
+
def is_input_error(self) -> bool:
|
|
55
|
+
"""Whether this is a 400 validation error — fix the request and retry."""
|
|
56
|
+
return self.status == 400
|
|
57
|
+
|
|
58
|
+
def is_state_error(self) -> bool:
|
|
59
|
+
"""Whether this is a 422 state error — resource is in the wrong state."""
|
|
60
|
+
return self.status == 422
|
|
61
|
+
|
|
62
|
+
def is_auth_error(self) -> bool:
|
|
63
|
+
"""Whether this is an auth error (401/403)."""
|
|
64
|
+
return self.status in (401, 403)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class AuthenticationError(APIError):
|
|
68
|
+
"""401 — invalid or missing API key."""
|
|
69
|
+
|
|
70
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
71
|
+
super().__init__(401, **kwargs)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class PermissionDeniedError(APIError):
|
|
75
|
+
"""403 — insufficient scopes or permissions."""
|
|
76
|
+
|
|
77
|
+
missing_scopes: list[str]
|
|
78
|
+
key_scopes: Optional[list[str]]
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
*,
|
|
83
|
+
missing_scopes: Optional[list[str]] = None,
|
|
84
|
+
key_scopes: Optional[list[str]] = None,
|
|
85
|
+
**kwargs: Any,
|
|
86
|
+
) -> None:
|
|
87
|
+
self.missing_scopes = missing_scopes or []
|
|
88
|
+
self.key_scopes = key_scopes
|
|
89
|
+
super().__init__(403, **kwargs)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class NotFoundError(APIError):
|
|
93
|
+
"""404 — resource not found."""
|
|
94
|
+
|
|
95
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
96
|
+
super().__init__(404, **kwargs)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class BadRequestError(APIError):
|
|
100
|
+
"""400 — request validation failed."""
|
|
101
|
+
|
|
102
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
103
|
+
super().__init__(400, **kwargs)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class UnprocessableError(APIError):
|
|
107
|
+
"""422 — resource in wrong state for the requested operation."""
|
|
108
|
+
|
|
109
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
110
|
+
super().__init__(422, **kwargs)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class RateLimitError(APIError):
|
|
114
|
+
"""429 — rate limit exceeded."""
|
|
115
|
+
|
|
116
|
+
retry_after: Optional[float]
|
|
117
|
+
|
|
118
|
+
def __init__(self, *, retry_after: Optional[float] = None, **kwargs: Any) -> None:
|
|
119
|
+
self.retry_after = retry_after
|
|
120
|
+
super().__init__(429, **kwargs)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class APIConnectionError(AgledgerError):
|
|
124
|
+
"""Network connectivity error."""
|
|
125
|
+
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class APITimeoutError(APIConnectionError):
|
|
130
|
+
"""Request timed out."""
|
|
131
|
+
|
|
132
|
+
pass
|