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.
Files changed (33) hide show
  1. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.claude/CLAUDE.md +1 -1
  2. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/PKG-INFO +3 -3
  3. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/README.md +1 -1
  4. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/client.py +7 -7
  5. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/types.py +20 -11
  6. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/pyproject.toml +2 -2
  7. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_client.py +16 -4
  8. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_integration.py +5 -2
  9. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/uv.lock +1 -1
  10. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  12. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  13. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/dependabot.yml +0 -0
  14. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/workflows/ci.yml +0 -0
  15. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/workflows/publish.yml +0 -0
  16. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.github/workflows/security.yml +0 -0
  17. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/.gitignore +0 -0
  18. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/CODE_OF_CONDUCT.md +0 -0
  19. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/CONTRIBUTING.md +0 -0
  20. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/LICENSE +0 -0
  21. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/SECURITY.md +0 -0
  22. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/__init__.py +0 -0
  23. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/errors.py +0 -0
  24. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/py.typed +0 -0
  25. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/agentscore/test_mode.py +0 -0
  26. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/lefthook.yml +0 -0
  27. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/ruff.toml +0 -0
  28. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/__init__.py +0 -0
  29. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/conftest.py +0 -0
  30. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_errors.py +0 -0
  31. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_test_mode.py +0 -0
  32. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/tests/test_types.py +0 -0
  33. {agentscore_py-2.0.0 → agentscore_py-2.0.2}/vulture_whitelist.py +0 -0
@@ -1,6 +1,6 @@
1
1
  # agentscore-py
2
2
 
3
- Python client for the AgentScore trust and reputation API.
3
+ Python client for the AgentScore APIs.
4
4
 
5
5
  ## Identity Model
6
6
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentscore-py
3
- Version: 2.0.0
4
- Summary: Python client for the AgentScore trust and reputation API
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
  [![PyPI version](https://img.shields.io/pypi/v/agentscore-py.svg)](https://pypi.org/project/agentscore-py/)
27
27
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
28
28
 
29
- Python client for the [AgentScore](https://agentscore.sh) trust and reputation API.
29
+ Python client for the [AgentScore](https://agentscore.sh) APIs.
30
30
 
31
31
  ## Install
32
32
 
@@ -3,7 +3,7 @@
3
3
  [![PyPI version](https://img.shields.io/pypi/v/agentscore-py.svg)](https://pypi.org/project/agentscore-py/)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
5
 
6
- Python client for the [AgentScore](https://agentscore.sh) trust and reputation API.
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 trust and reputation API."""
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 = False,
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"] = True
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 = False,
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"] = True
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
- "operator_verification_required",
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.0"
8
- description = "Python client for the AgentScore trust and reputation API"
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 test_assess_refresh_false_not_included_in_body():
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", "sanctions_check_pending"],
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", "sanctions_check_pending"],
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 "sanctions_check_pending" in result["decision_reasons"]
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", "http://api.dev.agentscore.internal")
8
+ BASE_URL = os.environ.get("AGENTSCORE_BASE_URL")
9
9
  TEST_ADDRESS = "0x339559a2d1cd15059365fc7bd36b3047bba480e0"
10
10
 
11
- pytestmark = pytest.mark.skipif(not API_KEY, reason="AGENTSCORE_API_KEY not set")
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():
@@ -4,7 +4,7 @@ requires-python = ">=3.11"
4
4
 
5
5
  [[package]]
6
6
  name = "agentscore-py"
7
- version = "2.0.0"
7
+ version = "2.0.2"
8
8
  source = { editable = "." }
9
9
  dependencies = [
10
10
  { name = "httpx" },
File without changes
File without changes
File without changes
File without changes