agentscore-py 2.0.0__tar.gz → 2.0.2__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.
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.claude/CLAUDE.md +1 -1
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/PKG-INFO +3 -3
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/README.md +1 -1
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/client.py +7 -7
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/types.py +20 -11
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/pyproject.toml +2 -2
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_client.py +16 -4
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_integration.py +5 -2
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/uv.lock +1 -1
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/dependabot.yml +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/workflows/ci.yml +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/workflows/publish.yml +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/workflows/security.yml +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.gitignore +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/CODE_OF_CONDUCT.md +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/CONTRIBUTING.md +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/LICENSE +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/SECURITY.md +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/__init__.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/errors.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/py.typed +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/test_mode.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/lefthook.yml +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/ruff.toml +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/__init__.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/conftest.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_errors.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_test_mode.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_types.py +0 -0
- {agentscore_py-2.0.0 → agentscore_py-2.0.2}/vulture_whitelist.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentscore-py
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary: Python client for the AgentScore
|
|
3
|
+
Version: 2.0.2
|
|
4
|
+
Summary: Python client for the AgentScore APIs
|
|
5
5
|
Project-URL: Homepage, https://agentscore.sh
|
|
6
6
|
Project-URL: Repository, https://github.com/agentscore/python-sdk
|
|
7
7
|
Project-URL: Issues, https://github.com/agentscore/python-sdk/issues
|
|
@@ -26,7 +26,7 @@ Description-Content-Type: text/markdown
|
|
|
26
26
|
[](https://pypi.org/project/agentscore-py/)
|
|
27
27
|
[](LICENSE)
|
|
28
28
|
|
|
29
|
-
Python client for the [AgentScore](https://agentscore.sh)
|
|
29
|
+
Python client for the [AgentScore](https://agentscore.sh) APIs.
|
|
30
30
|
|
|
31
31
|
## Install
|
|
32
32
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://pypi.org/project/agentscore-py/)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
Python client for the [AgentScore](https://agentscore.sh)
|
|
6
|
+
Python client for the [AgentScore](https://agentscore.sh) APIs.
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
class AgentScore:
|
|
45
|
-
"""Client for the AgentScore
|
|
45
|
+
"""Client for the AgentScore APIs."""
|
|
46
46
|
|
|
47
47
|
def __init__(
|
|
48
48
|
self,
|
|
@@ -153,7 +153,7 @@ class AgentScore:
|
|
|
153
153
|
self,
|
|
154
154
|
address: str | None = None,
|
|
155
155
|
chain: str | None = None,
|
|
156
|
-
refresh: bool =
|
|
156
|
+
refresh: bool | None = None,
|
|
157
157
|
policy: DecisionPolicy | None = None,
|
|
158
158
|
operator_token: str | None = None,
|
|
159
159
|
) -> AssessResponse:
|
|
@@ -165,8 +165,8 @@ class AgentScore:
|
|
|
165
165
|
body["operator_token"] = operator_token
|
|
166
166
|
if chain:
|
|
167
167
|
body["chain"] = chain
|
|
168
|
-
if refresh:
|
|
169
|
-
body["refresh"] =
|
|
168
|
+
if refresh is not None:
|
|
169
|
+
body["refresh"] = refresh
|
|
170
170
|
if policy is not None:
|
|
171
171
|
body["policy"] = dict(policy)
|
|
172
172
|
client = self._get_sync_client()
|
|
@@ -279,7 +279,7 @@ class AgentScore:
|
|
|
279
279
|
self,
|
|
280
280
|
address: str | None = None,
|
|
281
281
|
chain: str | None = None,
|
|
282
|
-
refresh: bool =
|
|
282
|
+
refresh: bool | None = None,
|
|
283
283
|
policy: DecisionPolicy | None = None,
|
|
284
284
|
operator_token: str | None = None,
|
|
285
285
|
) -> AssessResponse:
|
|
@@ -291,8 +291,8 @@ class AgentScore:
|
|
|
291
291
|
body["operator_token"] = operator_token
|
|
292
292
|
if chain:
|
|
293
293
|
body["chain"] = chain
|
|
294
|
-
if refresh:
|
|
295
|
-
body["refresh"] =
|
|
294
|
+
if refresh is not None:
|
|
295
|
+
body["refresh"] = refresh
|
|
296
296
|
if policy is not None:
|
|
297
297
|
body["policy"] = dict(policy)
|
|
298
298
|
client = self._get_async_client()
|
|
@@ -338,23 +338,32 @@ class AssociateWalletResponse(TypedDict):
|
|
|
338
338
|
|
|
339
339
|
|
|
340
340
|
DenialCode = Literal[
|
|
341
|
-
|
|
342
|
-
"compliance_denied",
|
|
343
|
-
"compliance_error",
|
|
344
|
-
"wallet_not_trusted",
|
|
341
|
+
# Gate-emitted codes from commerce middleware (canonical 9-element union)
|
|
345
342
|
"missing_identity",
|
|
346
343
|
"identity_verification_required",
|
|
347
|
-
"payment_required",
|
|
348
|
-
"api_error",
|
|
349
|
-
"kyc_required",
|
|
350
|
-
# Wallet-signer binding — claimed X-Wallet-Address must resolve to the same operator
|
|
351
|
-
# as the payment signer; wallet-auth is rejected on rails with no wallet signer.
|
|
352
|
-
"wallet_signer_mismatch",
|
|
353
|
-
"wallet_auth_requires_wallet_signing",
|
|
354
344
|
# Credential is no longer valid (revoked or past its TTL — the two cases share this
|
|
355
345
|
# code deliberately so the API doesn't leak which one). The 401 body carries an
|
|
356
346
|
# auto-minted session so agents recover without holding an API key.
|
|
357
347
|
"token_expired",
|
|
348
|
+
# Credential doesn't exist at all (typo, fabricated, never minted). Permanent state;
|
|
349
|
+
# no auto-session is issued because the agent may have other valid tokens to try.
|
|
350
|
+
"invalid_credential",
|
|
351
|
+
# Wallet-signer binding — claimed X-Wallet-Address must resolve to the same operator
|
|
352
|
+
# as the payment signer; wallet-auth is rejected on rails with no wallet signer.
|
|
353
|
+
"wallet_signer_mismatch",
|
|
354
|
+
"wallet_auth_requires_wallet_signing",
|
|
355
|
+
"wallet_not_trusted",
|
|
356
|
+
"api_error",
|
|
357
|
+
"payment_required",
|
|
358
|
+
# Merchant-emitted convenience codes — not emitted by the AgentScore API itself,
|
|
359
|
+
# but may appear in 4xx bodies passing through the SDK from merchants whose gate
|
|
360
|
+
# `on_denied` hook wraps AgentScore denials into business-domain codes.
|
|
361
|
+
"operator_verification_required",
|
|
362
|
+
"compliance_denied",
|
|
363
|
+
"compliance_error",
|
|
364
|
+
# Decision-reason code surfaced in error.code by some merchants — kept for back-compat
|
|
365
|
+
# with merchants that flatten policy reasons into the error envelope.
|
|
366
|
+
"kyc_required",
|
|
358
367
|
]
|
|
359
368
|
"""Denial codes returned by the gate in 403/402 error bodies. Lets agents pick the right
|
|
360
369
|
remediation without natural-language parsing."""
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentscore-py"
|
|
7
|
-
version = "2.0.
|
|
8
|
-
description = "Python client for the AgentScore
|
|
7
|
+
version = "2.0.2"
|
|
8
|
+
description = "Python client for the AgentScore APIs"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
requires-python = ">=3.11"
|
|
@@ -407,11 +407,23 @@ def test_user_agent_header_prepends_custom_user_agent():
|
|
|
407
407
|
|
|
408
408
|
|
|
409
409
|
@respx.mock
|
|
410
|
-
def
|
|
410
|
+
def test_assess_refresh_explicit_false_sent_in_body():
|
|
411
|
+
# Matches node-sdk semantics: when consumer explicitly passes refresh=False,
|
|
412
|
+
# the SDK includes `refresh: false` in the body. Default (no value passed)
|
|
413
|
+
# omits the field entirely.
|
|
411
414
|
route = respx.post(f"{BASE_URL}/v1/assess").mock(return_value=httpx.Response(200, json=ASSESS_PAYLOAD))
|
|
412
415
|
client = AgentScore(api_key=API_KEY)
|
|
413
416
|
client.assess(ADDRESS, refresh=False)
|
|
414
417
|
body = json.loads(route.calls.last.request.content)
|
|
418
|
+
assert body.get("refresh") is False
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
@respx.mock
|
|
422
|
+
def test_assess_refresh_omitted_when_default():
|
|
423
|
+
route = respx.post(f"{BASE_URL}/v1/assess").mock(return_value=httpx.Response(200, json=ASSESS_PAYLOAD))
|
|
424
|
+
client = AgentScore(api_key=API_KEY)
|
|
425
|
+
client.assess(ADDRESS)
|
|
426
|
+
body = json.loads(route.calls.last.request.content)
|
|
415
427
|
assert "refresh" not in body
|
|
416
428
|
|
|
417
429
|
|
|
@@ -515,7 +527,7 @@ REPUTATION_WITH_VERIFICATION = {
|
|
|
515
527
|
ASSESS_WITH_COMPLIANCE = {
|
|
516
528
|
**ASSESS_PAYLOAD,
|
|
517
529
|
"decision": "deny",
|
|
518
|
-
"decision_reasons": ["kyc_required", "
|
|
530
|
+
"decision_reasons": ["kyc_required", "sanctions_flagged"],
|
|
519
531
|
"operator_verification": {
|
|
520
532
|
"level": "none",
|
|
521
533
|
"operator_type": None,
|
|
@@ -633,7 +645,7 @@ def test_full_compliance_deny_flow():
|
|
|
633
645
|
compliance_response = {
|
|
634
646
|
**REPUTATION_PAYLOAD,
|
|
635
647
|
"decision": "deny",
|
|
636
|
-
"decision_reasons": ["kyc_required", "
|
|
648
|
+
"decision_reasons": ["kyc_required", "sanctions_flagged"],
|
|
637
649
|
"on_the_fly": False,
|
|
638
650
|
"operator_verification": {
|
|
639
651
|
"level": "none",
|
|
@@ -654,7 +666,7 @@ def test_full_compliance_deny_flow():
|
|
|
654
666
|
)
|
|
655
667
|
assert result["decision"] == "deny"
|
|
656
668
|
assert "kyc_required" in result["decision_reasons"]
|
|
657
|
-
assert "
|
|
669
|
+
assert "sanctions_flagged" in result["decision_reasons"]
|
|
658
670
|
assert result["verify_url"] == "https://agentscore.sh/verify/xyz789"
|
|
659
671
|
assert result["operator_verification"]["level"] == "none"
|
|
660
672
|
|
|
@@ -5,10 +5,13 @@ import pytest
|
|
|
5
5
|
from agentscore import AgentScore
|
|
6
6
|
|
|
7
7
|
API_KEY = os.environ.get("AGENTSCORE_API_KEY")
|
|
8
|
-
BASE_URL = os.environ.get("AGENTSCORE_BASE_URL"
|
|
8
|
+
BASE_URL = os.environ.get("AGENTSCORE_BASE_URL")
|
|
9
9
|
TEST_ADDRESS = "0x339559a2d1cd15059365fc7bd36b3047bba480e0"
|
|
10
10
|
|
|
11
|
-
pytestmark = pytest.mark.skipif(
|
|
11
|
+
pytestmark = pytest.mark.skipif(
|
|
12
|
+
not (API_KEY and BASE_URL),
|
|
13
|
+
reason="AGENTSCORE_API_KEY and AGENTSCORE_BASE_URL must both be set",
|
|
14
|
+
)
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
def test_get_reputation_shape():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|