Skip to content

Commit a44c5a6

Browse files
vvillait88claude
andcommitted
Bump dev tooling and release 2.5.13
Dependency refresh: ruff 0.16.0, ty 0.0.63, plus aiohttp, annotated-types, h2, httpcore2 and httpx2 moving with the resolver. The declared runtime dependencies are unchanged. Ruff 0.16.0 formats Python code blocks inside Markdown, which reformats the README examples. Applied rather than excluding Markdown from the format check, since narrowing the gate to avoid the tool's own style is the worse trade. Lifted the dependabot hold on ty. It was held because a pre-1.0 type checker's new rules churned CI; that problem is fixed, so ty now updates on the routine cadence and this repo matches its sibling, which never carried the ignore. Verified: ruff check, ruff format, ty and pytest all exit 0; 1841 tests pass at 95.36% coverage; vulture clean at the 80% confidence floor. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent c97d4f8 commit a44c5a6

4 files changed

Lines changed: 223 additions & 179 deletions

File tree

.github/dependabot.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,6 @@ updates:
1515
groups:
1616
minor-patch:
1717
update-types: ["minor", "patch"]
18-
ignore:
19-
# ty is exact-pinned: pre-1.0 type checker whose new rules churn CI;
20-
# bump deliberately, not in routine passes (2026-07-11)
21-
- dependency-name: "ty"
22-
2318
- package-ecosystem: "github-actions"
2419
directory: "/"
2520
cooldown:

README.md

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ _gate = AgentScoreGate(
7676
# proving identity. Identity is verified at settle time on the retry leg.
7777
from agentscore_commerce.payment import has_payment_header
7878

79+
7980
async def gate_on_settle(request: Request) -> None:
8081
if not has_payment_header(request):
8182
return None
@@ -97,14 +98,22 @@ async def purchase(request: Request, assess=Depends(get_agentscore_data)):
9798
```python
9899
from fastapi import FastAPI, Request
99100
from agentscore_commerce import (
100-
Checkout, CheckoutGateConfig, DiscoveryProbeConfig, PricingResult, pricing_result,
101-
SolanaMppRailSpec, StripeRailSpec, TempoRailSpec, X402BaseRailSpec,
101+
Checkout,
102+
CheckoutGateConfig,
103+
DiscoveryProbeConfig,
104+
PricingResult,
105+
pricing_result,
106+
SolanaMppRailSpec,
107+
StripeRailSpec,
108+
TempoRailSpec,
109+
X402BaseRailSpec,
102110
validate_shipping_against_policy,
103111
)
104112
from agentscore_commerce.discovery import default_a2a_services
105113

106114
app = FastAPI()
107115

116+
108117
async def _pre_validate(ctx):
109118
body = ctx.request.body or {}
110119
product = await lookup_product(body.get("product_slug"))
@@ -116,6 +125,7 @@ async def _pre_validate(ctx):
116125
)
117126
return {"product": product}
118127

128+
119129
async def _compute_pricing(ctx) -> PricingResult:
120130
return pricing_result(
121131
subtotal_cents=ctx.state["product"]["price_cents"],
@@ -124,15 +134,17 @@ async def _compute_pricing(ctx) -> PricingResult:
124134
tax_state=ctx.state["product"]["tax_state"],
125135
)
126136

137+
127138
async def _on_settled(ctx, outcome):
128139
return {"ok": True, "order_id": ctx.reference_id, "tx_hash": outcome.tx_hash}
129140

141+
130142
checkout = Checkout(
131143
rails={
132-
"tempo": TempoRailSpec(recipient=os.environ["TEMPO_RECIPIENT"]),
144+
"tempo": TempoRailSpec(recipient=os.environ["TEMPO_RECIPIENT"]),
133145
"x402_base": X402BaseRailSpec(recipient=os.environ["X402_BASE_RECIPIENT"], network="eip155:8453"),
134-
"solana_mpp":SolanaMppRailSpec(recipient=os.environ["SOLANA_RECIPIENT"], network="solana:mainnet"),
135-
"stripe": StripeRailSpec(profile_id=os.environ["STRIPE_PROFILE_ID"]),
146+
"solana_mpp": SolanaMppRailSpec(recipient=os.environ["SOLANA_RECIPIENT"], network="solana:mainnet"),
147+
"stripe": StripeRailSpec(profile_id=os.environ["STRIPE_PROFILE_ID"]),
136148
},
137149
url="https://merchant.example/purchase",
138150
pre_validate=_pre_validate,
@@ -144,7 +156,10 @@ checkout = Checkout(
144156
gate=CheckoutGateConfig(
145157
api_key=os.environ["AGENTSCORE_API_KEY"],
146158
merchant_name="Merchant",
147-
require_kyc=True, require_sanctions_clear=True, min_age=21, allowed_jurisdictions=["US"],
159+
require_kyc=True,
160+
require_sanctions_clear=True,
161+
min_age=21,
162+
allowed_jurisdictions=["US"],
148163
),
149164
# Optional: empty-body POSTs without a payment header auto-route to a sample 402
150165
# so x402 crawlers (awal x402 details, x402-proxy, ...) can discover the surface.
@@ -165,6 +180,7 @@ checkout.mount_ucp_routes_fastapi(
165180
signing_kid="merchant-2026-05",
166181
)
167182

183+
168184
@app.post("/purchase")
169185
async def purchase(request: Request):
170186
return await checkout.handle_fastapi(request)
@@ -192,10 +208,18 @@ from agentscore_commerce.payment import (
192208
# Build paymentauth.org directives by symbolic rail name (decimals + currency from registry)
193209
directives = [
194210
build_payment_directive(
195-
rail="tempo-mainnet", id="chg_t", realm="ex.com", recipient=TEMPO_ADDR, amount_usd=0.01,
211+
rail="tempo-mainnet",
212+
id="chg_t",
213+
realm="ex.com",
214+
recipient=TEMPO_ADDR,
215+
amount_usd=0.01,
196216
),
197217
build_payment_directive(
198-
rail="x402-base-mainnet", id="chg_b", realm="ex.com", recipient=BASE_ADDR, amount_usd=0.01,
218+
rail="x402-base-mainnet",
219+
id="chg_b",
220+
realm="ex.com",
221+
recipient=BASE_ADDR,
222+
amount_usd=0.01,
199223
),
200224
]
201225
www_auth = www_authenticate_header(directives)
@@ -229,7 +253,9 @@ from agentscore_commerce.challenge import (
229253
# build_accepted_methods + build_how_to_pay are async (they resolve per-order recipients).
230254
accepted = await build_accepted_methods(tempo=TempoRailSpec(recipient=TEMPO_ADDR))
231255
how_to_pay = await build_how_to_pay(
232-
url="https://my.merchant/buy", retry_body_json="{}", total_usd="10.00",
256+
url="https://my.merchant/buy",
257+
retry_body_json="{}",
258+
total_usd="10.00",
233259
rails={"tempo": TempoRailSpec(recipient=TEMPO_ADDR)},
234260
)
235261
body = build_402_body(
@@ -313,7 +339,7 @@ card = build_a2a_agent_card(
313339
# Google Universal Commerce Protocol. Publish at /.well-known/ucp.
314340
# Output shape: {"ucp": {"version", "services", "capabilities",
315341
# "payment_handlers", "name?", "supported_versions?"}, "signing_keys": [...]}
316-
#, services / capabilities / payment_handlers are MAPS keyed by reverse-DNS
342+
# , services / capabilities / payment_handlers are MAPS keyed by reverse-DNS
317343
# service / capability / handler name (UCP spec §3 + §6).
318344
profile = build_ucp_profile(
319345
name="My Service",
@@ -338,7 +364,9 @@ profile = build_ucp_profile(
338364
# binding inside the public profile. Static policy declaration only, no per-operator
339365
# claims. Per-operator identity attestation flows through the AP2 risk-signal endpoint.
340366
agentscore_gate=AgentScoreGatePolicy(
341-
require_kyc=True, min_age=21, allowed_jurisdictions=["US"],
367+
require_kyc=True,
368+
min_age=21,
369+
allowed_jurisdictions=["US"],
342370
),
343371
)
344372
```
@@ -452,6 +480,7 @@ from agentscore_commerce.payment import (
452480
# Boot-time guard. Raises if a configured network isn't supported.
453481
validate_x402_network_config(base_network=X402_BASE)
454482

483+
455484
@app.post("/purchase")
456485
async def purchase(request: Request):
457486
# Path A: agent presented an x402 X-Payment header
@@ -467,15 +496,24 @@ async def purchase(request: Request):
467496
settle = await process_x402_settle(
468497
x402_server=x402_server,
469498
payload=verified.payload,
470-
resource_config={"scheme": "exact", "network": verified.signed_network, "price": f"${total}", "payTo": verified.signed_pay_to, "maxTimeoutSeconds": 300},
499+
resource_config={
500+
"scheme": "exact",
501+
"network": verified.signed_network,
502+
"price": f"${total}",
503+
"payTo": verified.signed_pay_to,
504+
"maxTimeoutSeconds": 300,
505+
},
471506
resource_meta={"url": str(request.url), "mimeType": "application/json"},
472507
)
473508
classified = classify_x402_settle_result(settle)
474509
if classified is not None:
475510
# Log raw `settle` server-side; return controlled phase-based response to the agent.
476511
logger.error("x402-settle failed phase=%s raw=%r", settle.phase, settle)
477512
return JSONResponse(
478-
{"error": {"code": classified.code, "message": classified.message}, "next_steps": classified.next_steps},
513+
{
514+
"error": {"code": classified.code, "message": classified.message},
515+
"next_steps": classified.next_steps,
516+
},
479517
status_code=classified.status,
480518
)
481519

@@ -487,8 +525,18 @@ async def purchase(request: Request):
487525
# `body` is the dict from build_402_body; `x402` carries the payment_required_header kwargs.
488526
result = respond_402(
489527
mppx_challenge_headers=pympp_challenge_headers,
490-
body=build_402_body(accepted_methods=accepted, agent_instructions=instructions, pricing=pricing, amount_usd=total, retry_body=body),
491-
x402={"x402_version": 2, "accepts": x402_accepts, "resource": {"url": str(request.url), "mimeType": "application/json"}},
528+
body=build_402_body(
529+
accepted_methods=accepted,
530+
agent_instructions=instructions,
531+
pricing=pricing,
532+
amount_usd=total,
533+
retry_body=body,
534+
),
535+
x402={
536+
"x402_version": 2,
537+
"accepts": x402_accepts,
538+
"resource": {"url": str(request.url), "mimeType": "application/json"},
539+
},
492540
)
493541
return JSONResponse(result.body, status_code=result.status, headers=result.headers)
494542
```
@@ -504,6 +552,7 @@ from agentscore_commerce.identity.fastapi import AgentScoreGate, get_gate_degrad
504552
app = FastAPI()
505553
gate = AgentScoreGate(api_key=os.environ["AGENTSCORE_API_KEY"], fail_open=True)
506554

555+
507556
@app.post("/purchase", dependencies=[Depends(gate)])
508557
async def purchase(request: Request):
509558
state = get_gate_degraded_state(request)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "agentscore-commerce"
7-
version = "2.5.12"
7+
version = "2.5.13"
88
description = "Agent commerce SDK for Python — identity middleware (FastAPI, Flask, Django, AIOHTTP, Sanic, ASGI) + payment helpers + 402 builders + discovery + Stripe multichain. The full merchant-side toolkit for AgentScore-powered agent commerce."
99
readme = "README.md"
1010
license = "MIT"

0 commit comments

Comments
 (0)