-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagentkit_action_provider.py
More file actions
177 lines (142 loc) · 6.91 KB
/
agentkit_action_provider.py
File metadata and controls
177 lines (142 loc) · 6.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"""
AgentKit Action Provider for Accessibility Auditor.
Allows any AgentKit-powered AI agent to run a paid WCAG 2.1 accessibility
audit via x402 (0.10 USDC on Base Mainnet). Free audits are only available
via the website UI at https://hexdrive.tech.
Usage:
from agentkit_action_provider import accessibility_audit_action_provider
from coinbase_agentkit import AgentKit, AgentKitConfig
agent_kit = AgentKit(AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
accessibility_audit_action_provider(),
]
))
"""
from __future__ import annotations
import json
import os
from typing import Any
import httpx
from pydantic import BaseModel, Field
SERVER_URL = os.getenv("AUDIT_SERVER_URL", "https://hexdrive.tech")
# ── Schemas ────────────────────────────────────────────────────────────────────
class PaidAuditUrlSchema(BaseModel):
url: str = Field(
description="The URL of the website to audit for WCAG 2.1 accessibility compliance."
)
private_key: str = Field(
description="EVM private key of the wallet to pay with (0.10 USDC on Base Mainnet)."
)
# ── Paid audit action ──────────────────────────────────────────────────────────
def run_paid_accessibility_audit(args: dict[str, Any]) -> str:
"""
Run a paid WCAG 2.1 accessibility audit via x402 (0.10 USDC on Base Mainnet).
Automatically handles payment: signs EIP-3009 authorization and submits to facilitator.
"""
import asyncio
from eth_account import Account
from x402.client import x402Client
from x402.http.clients.httpx import x402HttpxClient
from x402.mechanisms.evm.exact.client import ExactEvmScheme
from x402.mechanisms.evm.signers import EthAccountSigner
url = args["url"]
private_key = args["private_key"]
async def _pay_and_audit():
account = Account.from_key(private_key)
signer = EthAccountSigner(account)
scheme = ExactEvmScheme(signer=signer)
client = x402Client()
client.register("eip155:84532", scheme) # Base Sepolia
async with x402HttpxClient(client) as http:
response = await http.post(
f"{SERVER_URL}/api/audit/paid",
json={"url": url},
timeout=90,
)
if response.status_code == 200:
data = response.json()
return {
"success": True,
"paid": True,
"payer": account.address,
"url": data.get("url", url),
"score": data.get("score"),
"grade": data.get("grade"),
"total_issues": data.get("total_issues"),
"critical": data.get("critical"),
"warnings": data.get("warnings"),
"issues_by_category": data.get("issues_by_category", {}),
"report_url": data.get("report_url"),
"audit_id": data.get("audit_id"),
"payment_network": data.get("payment_network"),
}
else:
return {"success": False, "error": f"HTTP {response.status_code}: {response.text[:200]}"}
try:
result = asyncio.run(_pay_and_audit())
return json.dumps(result)
except Exception as e:
return json.dumps({"success": False, "error": str(e)})
# ── AgentKit Action Provider ───────────────────────────────────────────────────
def accessibility_audit_action_provider():
"""
Returns an AgentKit ActionProvider for accessibility auditing.
Provides two actions:
- accessibility_free_audit: Free WCAG 2.1 audit (no payment)
- accessibility_paid_audit: Paid audit via x402 (0.10 USDC on Base Mainnet)
Example:
agent_kit = AgentKit(AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[accessibility_audit_action_provider()]
))
"""
try:
from coinbase_agentkit import ActionProvider, WalletProvider, create_action
from coinbase_agentkit.network import Network
class AccessibilityAuditActionProvider(ActionProvider):
def __init__(self):
super().__init__("accessibility-audit", [])
@create_action(
name="accessibility_paid_audit",
description=(
"Run a PAID WCAG 2.1 accessibility audit on a website via x402 protocol. "
"Costs 0.10 USDC on Base Mainnet. Payment is automatic via EIP-3009. "
"Returns full audit report with score, grade, and issue details. "
"Requires a wallet private key with at least 0.10 USDC on Base Mainnet."
),
schema=PaidAuditUrlSchema,
)
def paid_audit(self, args: dict[str, Any]) -> str:
return run_paid_accessibility_audit(args)
def supports_network(self, network: Network) -> bool:
return True
return AccessibilityAuditActionProvider()
except ImportError:
# coinbase-agentkit not installed — return a simple dict describing the actions
# so the module can still be imported and used standalone
return {
"name": "accessibility-audit",
"actions": {
"accessibility_paid_audit": run_paid_accessibility_audit,
},
"description": "WCAG 2.1 accessibility audit service (paid, via x402). Install coinbase-agentkit for full AgentKit integration.",
}
# ── Standalone usage (without AgentKit) ───────────────────────────────────────
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Usage: python agentkit_action_provider.py <url> [--paid <private_key>]")
print("Example (free): python agentkit_action_provider.py https://example.com")
print("Example (paid): python agentkit_action_provider.py https://example.com --paid 0xabc...")
sys.exit(1)
target_url = sys.argv[1]
if "--paid" not in sys.argv:
print("Error: private key required. Use --paid <private_key>")
print("Example: python agentkit_action_provider.py https://example.com --paid 0xabc...")
sys.exit(1)
idx = sys.argv.index("--paid")
pk = sys.argv[idx + 1]
print(f"Running PAID audit of {target_url} (0.10 USDC on Base Mainnet)...")
result = run_paid_accessibility_audit({"url": target_url, "private_key": pk})
print(json.dumps(json.loads(result), indent=2, ensure_ascii=False))