Skip to content

Commit 4b30dcc

Browse files
vvillait88claude
andcommitted
Remove em-dashes from served discovery copy; 2.7.2
Mirror of the Node SDK change, string for string, so both render the same shared identity and payment blocks. Every string these builders emit onto a merchant's llms.txt, skill.md, OpenAPI and 402 body is now free of em-dashes, which the house rule bars on external surfaces. The empty compatible-clients table cell rendered a bare em-dash; it now reads "none", matching the Node SDK. Also corrects "agent-commerce" to "agentic-commerce" in five docstrings: that is the house category term. Docstrings and comments are otherwise untouched: internal prose, not served, and they carry the rationale. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent e712055 commit 4b30dcc

8 files changed

Lines changed: 34 additions & 30 deletions

File tree

agentscore_commerce/challenge/how_to_pay.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ async def build_how_to_pay(
104104
"what_it_does": (
105105
f"Hits this endpoint, receives this same 402, signs the MPP challenge on {network_name}, and "
106106
"submits the credential back via Authorization: Payment. Either client (tempo request or "
107-
"agentscore-pay pay --chain tempo) works both run the full MPP handshake."
107+
"agentscore-pay pay --chain tempo) works; both run the full MPP handshake."
108108
),
109109
}
110110
if recommend == "both":
@@ -203,7 +203,7 @@ async def build_how_to_pay(
203203
)
204204
elif link_cli_blocked:
205205
stripe_block["note"] = (
206-
"link-cli SPT path not available for this purchase Stripe link-cli caps spend requests at $500.00 "
206+
"link-cli SPT path not available for this purchase: Stripe link-cli caps spend requests at $500.00 "
207207
f"($50000 cents); your total is ${total_num}. Use your own Stripe account with the SharedPaymentToken "
208208
"API instead."
209209
)

agentscore_commerce/checkout.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""High-level Checkout orchestrator; composes 402-emit + verify+settle.
22
3-
The Checkout primitive collapses the agent-commerce dance (emit 402 →
3+
The Checkout primitive collapses the agentic-commerce dance (emit 402 →
44
verify+settle on retry → respond) into a single ``await
55
checkout.handle(request)`` call. It services every merchant shape:
66
@@ -30,7 +30,7 @@
3030
``reference_id`` (a UUID minted on first contact). Goods merchants persist
3131
this as their order id; API merchants treat it as a per-call request id.
3232
33-
Usage (goods seller, full agent-commerce flow)::
33+
Usage (goods seller, full agentic-commerce flow)::
3434
3535
checkout = Checkout(
3636
rails={
@@ -811,7 +811,7 @@ def _strip_payment_headers_from_raw(raw: Any) -> Any:
811811

812812

813813
class Checkout:
814-
"""High-level agent-commerce orchestrator.
814+
"""High-level agentic-commerce orchestrator.
815815
816816
Composes :func:`build_accepted_methods`, :func:`build_how_to_pay`,
817817
:func:`respond_402`, :func:`verify_x402_request`, and
@@ -1116,7 +1116,7 @@ def _x402_base_network(self) -> str | None:
11161116
return None
11171117

11181118
async def handle(self, request: CheckoutRequest) -> CheckoutResult:
1119-
"""One-call agent-commerce flow.
1119+
"""One-call agentic-commerce flow.
11201120
11211121
* x402 ``X-Payment`` header present → verify, settle via ``x402_server``,
11221122
run ``on_settled`` hook, return 200 with the hook's body (or

agentscore_commerce/discovery/agentscore_content.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def build_agentscore_onboarding_steps(
101101
compatible_fragment = ", ".join(hint for rail, hint in compatible_hints if rail in accepted_rails)
102102

103103
compatible_clients_clause = (
104-
f"the rails table also lists per-rail `compatible_clients` {compatible_fragment}. "
104+
f"the rails table also lists per-rail `compatible_clients`: {compatible_fragment}. "
105105
if compatible_fragment
106106
else ""
107107
)
@@ -114,7 +114,7 @@ def build_agentscore_onboarding_steps(
114114
)
115115
bootstrap_step = (
116116
"First-run only: bootstrap wallet + Passport. Run `agentscore-pay agent-guide --json` "
117-
"for the canonical cold-start path it walks `agentscore-pay init` "
117+
"for the canonical cold-start path; it walks `agentscore-pay init` "
118118
"(creates keystore + per-chain wallet), `agentscore-pay passport login` "
119119
f"(one-time KYC{'; required for this merchant' if requires_kyc else ''}; "
120120
"the human completes a verify URL once and pay caches the operator_token), "
@@ -123,7 +123,7 @@ def build_agentscore_onboarding_steps(
123123
)
124124
stripe_fallback_step = (
125125
"If your only payment method is a Stripe / Link card (no crypto), install `@stripe/link-cli` "
126-
"instead of agentscore-pay and use it on the SPT rail. Identity gating still applies the "
126+
"instead of agentscore-pay and use it on the SPT rail. Identity gating still applies: the "
127127
"merchant's 403 with `verify_url` lets you bootstrap a Passport even with no crypto wallet involved."
128128
)
129129
returning_user_step = (

agentscore_commerce/discovery/llms_txt.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def llms_txt_identity_section(
2828
aip_bullet = ""
2929
if aip:
3030
aip_bullet = (
31-
"\n- **`Agent-Identity: <JWT>` + RFC 9421 signature** present an Agent Identity Token (AIP) "
31+
"\n- **`Agent-Identity: <JWT>` + RFC 9421 signature**: present an Agent Identity Token (AIP) "
3232
"from a trusted issuer (AgentScore is always trusted). Short-lived and bound to your key; sign "
3333
"the request (`Signature-Input` + `Signature` over `@method @authority @path agent-identity`, "
3434
"tag `agent-identity`) to prove possession. No long-lived token on the wire. Mint one with "
@@ -50,13 +50,13 @@ def llms_txt_identity_section(
5050
compliance_note = f"\n\nCompliance: {', '.join(parts)}."
5151
return (
5252
"## Identity\n\n"
53-
"AgentScore identity is reusable across every AgentScore-gated merchant one KYC, "
53+
"AgentScore identity is reusable across every AgentScore-gated merchant: one KYC, "
5454
"no re-verification per site. Pick a header:\n\n"
55-
"- **`X-Wallet-Address: 0x...` or base58** works on signing rails (Tempo, x402, "
55+
"- **`X-Wallet-Address: 0x...` or base58**: works on signing rails (Tempo, x402, "
5656
"Solana MPP). The wallet you claim must sign the payment.\n"
57-
"- **`X-Operator-Token: opc_...`** works on every rail, including Stripe SPT. "
57+
"- **`X-Operator-Token: opc_...`**: works on every rail, including Stripe SPT. "
5858
f"Reusable across AgentScore merchants until expiry.{aip_bullet}\n"
59-
"- **Neither** you get a 403 with `verify_url`. Complete the session flow once and "
59+
"- **Neither**: you get a 403 with `verify_url`. Complete the session flow once and "
6060
f"reuse the resulting `opc_...` everywhere.{compliance_note}"
6161
)
6262

@@ -103,22 +103,22 @@ def _llms_txt_payment_section_compact(*, rails: list[str], app_url: str) -> str:
103103
rails_list = list(rails)
104104
if _has_rail_family(rails_list, "tempo-"):
105105
lines.append(
106-
"- **Tempo USDC via MPP** "
106+
"- **Tempo USDC via MPP**: "
107107
f"`tempo request -X POST -H \"X-Operator-Token: opc_...\" --json '{{...}}' --max-spend N {app_url}`"
108108
)
109109
if _has_rail_family(rails_list, "x402-base-"):
110110
lines.append(
111-
f"- **x402 USDC on Base** (EIP-3009) `agentscore-pay pay POST {app_url} --chain base "
111+
f"- **x402 USDC on Base** (EIP-3009): `agentscore-pay pay POST {app_url} --chain base "
112112
"-H \"X-Operator-Token: opc_...\" -d '{...}'`"
113113
)
114114
if _has_rail_family(rails_list, "mpp-solana-"):
115115
lines.append(
116-
f"- **USDC on Solana** `agentscore-pay pay POST {app_url} --chain solana "
116+
f"- **USDC on Solana**: `agentscore-pay pay POST {app_url} --chain solana "
117117
"-H \"X-Operator-Token: opc_...\" -d '{...}'`"
118118
)
119119
if "stripe-spt" in rails_list:
120120
lines.append(
121-
"- **Stripe Shared Payment Token** agent mints SPT (own Stripe account scoped to networkId, "
121+
"- **Stripe Shared Payment Token**: agent mints SPT (own Stripe account scoped to networkId, "
122122
"OR `link-cli spend-request create --credential-type shared_payment_token --network-id "
123123
"<profileId> ...`)"
124124
)

agentscore_commerce/discovery/openapi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def agentscore_denial_schemas() -> dict[str, Any]:
233233
"token_expired → deliver_verify_url_and_poll, invalid_credential → "
234234
"switch_token_or_restart_session, wallet_signer_mismatch → resign_or_switch_to_operator_token, "
235235
"wallet_auth_requires_wallet_signing → switch_to_operator_token, wallet_not_trusted → "
236-
"contact_support UNFIXABLE compliance only (sanctions/age/jurisdiction_restricted); "
236+
"contact_support, for UNFIXABLE compliance only (sanctions/age/jurisdiction_restricted); "
237237
"fixable reasons re-route to identity_verification_required, payment_required → contact_merchant)."
238238
),
239239
},
@@ -255,7 +255,7 @@ def agentscore_denial_schemas() -> dict[str, Any]:
255255
"description": (
256256
"Present for missing_identity / identity_verification_required / token_expired "
257257
"denials. Agent shares this with the user to complete KYC or claim a wallet. "
258-
"Not present on wallet_not_trusted (UNFIXABLE compliance re-verification "
258+
"Not present on wallet_not_trusted (UNFIXABLE compliance, so re-verification "
259259
"won't change the outcome)."
260260
),
261261
},

agentscore_commerce/discovery/skill_md.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class _SkillCtx:
124124
"USDC (SPL). Use `agentscore-pay pay --chain solana`; MPP credential goes in `Authorization: Payment`."
125125
),
126126
"stripe": (
127-
"Card via Link wallet. Use `@stripe/link-cli` `agentscore-pay` emits the "
127+
"Card via Link wallet. Use `@stripe/link-cli`; `agentscore-pay` emits the "
128128
"handoff hint when this rail is picked."
129129
),
130130
}
@@ -141,7 +141,7 @@ def _validate(input: _SkillCtx) -> None:
141141
raise ValueError(f"build_skill_md: name must be 1-{_NAME_MAX} characters (got {len(n) if n else 0})")
142142
if not _NAME_RE.match(n):
143143
raise ValueError(
144-
f'build_skill_md: name "{n}" is invalid must be lowercase alphanumeric and hyphens, '
144+
f'build_skill_md: name "{n}" is invalid: must be lowercase alphanumeric and hyphens, '
145145
"no leading/trailing/consecutive hyphens (agentskills.io spec)"
146146
)
147147
if not input.description:
@@ -232,7 +232,7 @@ def _payment_section(input: _SkillCtx) -> str:
232232
clients[r] = defaults.get(r, [])
233233
rows = ["| Rail | Notes | Compatible clients |", "|---|---|---|"]
234234
for r in input.accepted_rails:
235-
client_list = ", ".join(clients.get(r, [])) or ""
235+
client_list = ", ".join(clients.get(r, [])) or "none"
236236
rows.append(f"| **{_RAIL_LABELS[r]}** | {_RAIL_NOTES[r]} | {client_list} |")
237237
intro = (
238238
"Each gated route returns a 402 with `WWW-Authenticate` + `PAYMENT-REQUIRED` "
@@ -276,12 +276,12 @@ def _identity_section(input: _SkillCtx) -> str:
276276
"\n\nThis merchant accepts AIP Agent Identity Tokens. If you hold an AIT from a trusted issuer "
277277
"(AgentScore is always trusted), present the JWT in an `Agent-Identity` header plus an RFC 9421 "
278278
"HTTP Message Signature (`Signature-Input` + `Signature` over `@method @authority @path agent-identity`, "
279-
"tag `agent-identity`) signed with the token-bound cnf key — it satisfies identity in one round trip, "
279+
"tag `agent-identity`) signed with the token-bound cnf key, satisfying identity in one round trip, "
280280
"no separate AgentScore credential needed. `agentscore-pay pay --identity aip` does this automatically."
281281
)
282282
denial_note = (
283-
"Denial bodies carry an `agent_instructions` block describing the recovery action "
284-
"— read the `action` field and follow it. See the identity-bootstrap skill for the "
283+
"Denial bodies carry an `agent_instructions` block describing the recovery action. "
284+
"Read the `action` field and follow it. See the identity-bootstrap skill for the "
285285
"canonical denial-code → action table."
286286
)
287287
return "\n".join(
@@ -375,7 +375,7 @@ def build_skill_md(
375375
support_links: list[SkillMdLink] | None = None,
376376
refresh_footer: bool = True,
377377
) -> str:
378-
"""Render an agentskills.io-compatible ``skill.md`` for an agent-commerce merchant.
378+
"""Render an agentskills.io-compatible ``skill.md`` for an agentic-commerce merchant.
379379
380380
Output is YAML frontmatter (``name`` / ``description`` / optional ``license`` /
381381
``compatibility`` / ``allowed-tools`` / ``metadata``) followed by markdown sections

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.7.1"
7+
version = "2.7.2"
88
description = "Agentic 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 agentic commerce."
99
readme = "README.md"
1010
license = "MIT"

tests/test_skill_md.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,16 @@ def test_drops_overrides_for_rails_not_in_accepted(self) -> None:
253253
assert "rogue-cli" not in out
254254
assert "Stripe Shared Payment Token" not in out
255255

256-
def test_renders_em_dash_when_clients_empty(self) -> None:
256+
def test_renders_none_when_clients_empty(self) -> None:
257+
# "none" rather than an em-dash: this table is served on every store's
258+
# skill.md, and the org rule bars em-dashes on external surfaces. Kept
259+
# identical to the Node SDK, which renders the same table.
257260
cfg = _base()
258261
cfg["accepted_rails"] = ["x402_base"]
259262
cfg["compatible_clients"] = {"x402_base": []}
260263
out = build_skill_md(**cfg)
261-
assert re.search("x402 on Base.+\\| —", out)
264+
assert re.search(r"x402 on Base.+\| none", out)
265+
assert "—" not in out
262266

263267

264268
class TestIdentitySection:

0 commit comments

Comments
 (0)