sweetai-agent-firewall 0.1.0__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.
- sweetai_agent_firewall-0.1.0/LICENSE +21 -0
- sweetai_agent_firewall-0.1.0/PKG-INFO +69 -0
- sweetai_agent_firewall-0.1.0/README.md +46 -0
- sweetai_agent_firewall-0.1.0/pyproject.toml +35 -0
- sweetai_agent_firewall-0.1.0/setup.cfg +4 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_agent_firewall.egg-info/PKG-INFO +69 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_agent_firewall.egg-info/SOURCES.txt +10 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_agent_firewall.egg-info/dependency_links.txt +1 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_agent_firewall.egg-info/requires.txt +1 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_agent_firewall.egg-info/top_level.txt +1 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_firewall/__init__.py +16 -0
- sweetai_agent_firewall-0.1.0/src/sweetai_firewall/client.py +164 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SweetAI (tiamatcrypto.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sweetai-agent-firewall
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pre-transaction trust firewall for AI agents: should-i-pay decisions, sybil forensics, liveness SLA (SweetAI x402 / ERC-8004)
|
|
5
|
+
Author-email: SweetAI <tiamatboss@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://sweetai.tiamatcrypto.com
|
|
8
|
+
Project-URL: Documentation, https://sweetai.tiamatcrypto.com/llms.txt
|
|
9
|
+
Project-URL: MCP, https://sweetai.tiamatcrypto.com/mcp
|
|
10
|
+
Project-URL: Source, https://sweetai.tiamatcrypto.com/agent.json
|
|
11
|
+
Keywords: x402,erc-8004,ai-agents,agent-payments,sybil,trust,mcp,crypto,usdc,base,solana,a2a
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: httpx>=0.24
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# sweetai-agent-firewall
|
|
25
|
+
|
|
26
|
+
**Pre-transaction trust firewall for AI agents.** Ask *"should I pay agent X $N?"* before any agent-to-agent payment — one call, $0.02, no API key, no subscription (x402 / USDC).
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from sweetai_firewall import SweetAIFirewall
|
|
30
|
+
|
|
31
|
+
fw = SweetAIFirewall()
|
|
32
|
+
result = fw.should_i_pay(agent_id=55985, amount_usd=25)
|
|
33
|
+
print(result.verdict)
|
|
34
|
+
# pay 0.02 USDC on eip155:8453, ... to 0x... to unlock the 25.0 USD decision
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
After your agent settles the 0.02 USDC payment (x402 `X-PAYMENT` header), the
|
|
38
|
+
same call returns the full decision:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
result.action # "PAY" / "CAUTION" / "SKIP"
|
|
42
|
+
result.confidence # 0.0 - 1.0
|
|
43
|
+
result.expected_loss_usd # expected loss sized to YOUR amount
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## What's under the hood
|
|
47
|
+
|
|
48
|
+
- **ERC-8004 / Solana-8004 on-chain feedback** analytics (Base, Ethereum, X Layer, Solana, Bittensor)
|
|
49
|
+
- **Sybil forensics**: reviewer concentration (Herfindahl), ghost-reviewer ratio, burst detection
|
|
50
|
+
- **Liveness SLA**: p50/p95 latency + flap counts, probed every 15 min
|
|
51
|
+
- **x402 pay-per-call**: 0.02 USDC per decision on Base/Polygon/Arbitrum/Avalanche/Sei/X Layer/Solana
|
|
52
|
+
|
|
53
|
+
## Free surfaces (no payment needed)
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
fw.status() # live index stats
|
|
57
|
+
fw.network_sybil_overview() # risk tiers across all indexed agents
|
|
58
|
+
fw.pricing() # current prices
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## MCP alternative
|
|
62
|
+
|
|
63
|
+
All tools are also available as an MCP server for Claude Desktop / Cursor / any MCP agent:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{"mcpServers": {"sweetai-agent-intel": {"url": "https://sweetai.tiamatcrypto.com/mcp", "transport": "http"}}}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Docs: <https://sweetai.tiamatcrypto.com/llms.txt> · Manifest: `/.well-known/x402` · agent.json: `/agent.json`
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# sweetai-agent-firewall
|
|
2
|
+
|
|
3
|
+
**Pre-transaction trust firewall for AI agents.** Ask *"should I pay agent X $N?"* before any agent-to-agent payment — one call, $0.02, no API key, no subscription (x402 / USDC).
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from sweetai_firewall import SweetAIFirewall
|
|
7
|
+
|
|
8
|
+
fw = SweetAIFirewall()
|
|
9
|
+
result = fw.should_i_pay(agent_id=55985, amount_usd=25)
|
|
10
|
+
print(result.verdict)
|
|
11
|
+
# pay 0.02 USDC on eip155:8453, ... to 0x... to unlock the 25.0 USD decision
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
After your agent settles the 0.02 USDC payment (x402 `X-PAYMENT` header), the
|
|
15
|
+
same call returns the full decision:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
result.action # "PAY" / "CAUTION" / "SKIP"
|
|
19
|
+
result.confidence # 0.0 - 1.0
|
|
20
|
+
result.expected_loss_usd # expected loss sized to YOUR amount
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What's under the hood
|
|
24
|
+
|
|
25
|
+
- **ERC-8004 / Solana-8004 on-chain feedback** analytics (Base, Ethereum, X Layer, Solana, Bittensor)
|
|
26
|
+
- **Sybil forensics**: reviewer concentration (Herfindahl), ghost-reviewer ratio, burst detection
|
|
27
|
+
- **Liveness SLA**: p50/p95 latency + flap counts, probed every 15 min
|
|
28
|
+
- **x402 pay-per-call**: 0.02 USDC per decision on Base/Polygon/Arbitrum/Avalanche/Sei/X Layer/Solana
|
|
29
|
+
|
|
30
|
+
## Free surfaces (no payment needed)
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
fw.status() # live index stats
|
|
34
|
+
fw.network_sybil_overview() # risk tiers across all indexed agents
|
|
35
|
+
fw.pricing() # current prices
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## MCP alternative
|
|
39
|
+
|
|
40
|
+
All tools are also available as an MCP server for Claude Desktop / Cursor / any MCP agent:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{"mcpServers": {"sweetai-agent-intel": {"url": "https://sweetai.tiamatcrypto.com/mcp", "transport": "http"}}}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Docs: <https://sweetai.tiamatcrypto.com/llms.txt> · Manifest: `/.well-known/x402` · agent.json: `/agent.json`
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sweetai-agent-firewall"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Pre-transaction trust firewall for AI agents: should-i-pay decisions, sybil forensics, liveness SLA (SweetAI x402 / ERC-8004)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "SweetAI", email = "tiamatboss@gmail.com"}]
|
|
13
|
+
keywords = [
|
|
14
|
+
"x402", "erc-8004", "ai-agents", "agent-payments", "sybil",
|
|
15
|
+
"trust", "mcp", "crypto", "usdc", "base", "solana", "a2a",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
23
|
+
"Topic :: Security",
|
|
24
|
+
]
|
|
25
|
+
dependencies = ["httpx>=0.24"]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://sweetai.tiamatcrypto.com"
|
|
29
|
+
Documentation = "https://sweetai.tiamatcrypto.com/llms.txt"
|
|
30
|
+
MCP = "https://sweetai.tiamatcrypto.com/mcp"
|
|
31
|
+
Source = "https://sweetai.tiamatcrypto.com/agent.json"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools]
|
|
34
|
+
packages = ["sweetai_firewall"]
|
|
35
|
+
package-dir = {"" = "src"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sweetai-agent-firewall
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pre-transaction trust firewall for AI agents: should-i-pay decisions, sybil forensics, liveness SLA (SweetAI x402 / ERC-8004)
|
|
5
|
+
Author-email: SweetAI <tiamatboss@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://sweetai.tiamatcrypto.com
|
|
8
|
+
Project-URL: Documentation, https://sweetai.tiamatcrypto.com/llms.txt
|
|
9
|
+
Project-URL: MCP, https://sweetai.tiamatcrypto.com/mcp
|
|
10
|
+
Project-URL: Source, https://sweetai.tiamatcrypto.com/agent.json
|
|
11
|
+
Keywords: x402,erc-8004,ai-agents,agent-payments,sybil,trust,mcp,crypto,usdc,base,solana,a2a
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: httpx>=0.24
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# sweetai-agent-firewall
|
|
25
|
+
|
|
26
|
+
**Pre-transaction trust firewall for AI agents.** Ask *"should I pay agent X $N?"* before any agent-to-agent payment — one call, $0.02, no API key, no subscription (x402 / USDC).
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from sweetai_firewall import SweetAIFirewall
|
|
30
|
+
|
|
31
|
+
fw = SweetAIFirewall()
|
|
32
|
+
result = fw.should_i_pay(agent_id=55985, amount_usd=25)
|
|
33
|
+
print(result.verdict)
|
|
34
|
+
# pay 0.02 USDC on eip155:8453, ... to 0x... to unlock the 25.0 USD decision
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
After your agent settles the 0.02 USDC payment (x402 `X-PAYMENT` header), the
|
|
38
|
+
same call returns the full decision:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
result.action # "PAY" / "CAUTION" / "SKIP"
|
|
42
|
+
result.confidence # 0.0 - 1.0
|
|
43
|
+
result.expected_loss_usd # expected loss sized to YOUR amount
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## What's under the hood
|
|
47
|
+
|
|
48
|
+
- **ERC-8004 / Solana-8004 on-chain feedback** analytics (Base, Ethereum, X Layer, Solana, Bittensor)
|
|
49
|
+
- **Sybil forensics**: reviewer concentration (Herfindahl), ghost-reviewer ratio, burst detection
|
|
50
|
+
- **Liveness SLA**: p50/p95 latency + flap counts, probed every 15 min
|
|
51
|
+
- **x402 pay-per-call**: 0.02 USDC per decision on Base/Polygon/Arbitrum/Avalanche/Sei/X Layer/Solana
|
|
52
|
+
|
|
53
|
+
## Free surfaces (no payment needed)
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
fw.status() # live index stats
|
|
57
|
+
fw.network_sybil_overview() # risk tiers across all indexed agents
|
|
58
|
+
fw.pricing() # current prices
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## MCP alternative
|
|
62
|
+
|
|
63
|
+
All tools are also available as an MCP server for Claude Desktop / Cursor / any MCP agent:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{"mcpServers": {"sweetai-agent-intel": {"url": "https://sweetai.tiamatcrypto.com/mcp", "transport": "http"}}}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Docs: <https://sweetai.tiamatcrypto.com/llms.txt> · Manifest: `/.well-known/x402` · agent.json: `/agent.json`
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/sweetai_agent_firewall.egg-info/PKG-INFO
|
|
5
|
+
src/sweetai_agent_firewall.egg-info/SOURCES.txt
|
|
6
|
+
src/sweetai_agent_firewall.egg-info/dependency_links.txt
|
|
7
|
+
src/sweetai_agent_firewall.egg-info/requires.txt
|
|
8
|
+
src/sweetai_agent_firewall.egg-info/top_level.txt
|
|
9
|
+
src/sweetai_firewall/__init__.py
|
|
10
|
+
src/sweetai_firewall/client.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
httpx>=0.24
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sweetai_firewall
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""SweetAI pre-transaction trust firewall for AI agents.
|
|
2
|
+
|
|
3
|
+
One call before any agent-to-agent payment:
|
|
4
|
+
|
|
5
|
+
from sweetai_firewall import SweetAIFirewall
|
|
6
|
+
fw = SweetAIFirewall()
|
|
7
|
+
fw.should_i_pay(agent_id=55985, amount_usd=25)
|
|
8
|
+
# -> {"action": "SKIP", "confidence": 0.9, "expected_loss_usd": 22.5, ...}
|
|
9
|
+
|
|
10
|
+
Pay $0.02 per call via x402 (USDC, Base/Polygon/Arbitrum/Avalanche/Sei/X Layer/Solana).
|
|
11
|
+
No API key, no subscription.
|
|
12
|
+
"""
|
|
13
|
+
from .client import SweetAIFirewall, ShouldIPayResult
|
|
14
|
+
|
|
15
|
+
__all__ = ["SweetAIFirewall", "ShouldIPayResult"]
|
|
16
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""HTTP client for the SweetAI x402 trust API.
|
|
2
|
+
|
|
3
|
+
The firewall endpoints are pay-per-call via the x402 protocol: the first
|
|
4
|
+
request returns HTTP 402 with a PAYMENT-REQUIRED header describing exactly
|
|
5
|
+
what to pay, to whom, on which chain. This client does three things:
|
|
6
|
+
|
|
7
|
+
1. Free endpoints (/status, teaser aggregates) are plain GETs.
|
|
8
|
+
2. ``should_i_pay`` / ``trust_forensics`` surface the 402 payment
|
|
9
|
+
requirements in a structured, agent-readable form (the caller — an AI
|
|
10
|
+
agent with a wallet — completes the x402 payment itself).
|
|
11
|
+
3. Nothing is ever cached longer than the answer's own TTL.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import base64
|
|
16
|
+
from dataclasses import dataclass, field
|
|
17
|
+
from typing import Any, Dict, Optional
|
|
18
|
+
|
|
19
|
+
import httpx
|
|
20
|
+
|
|
21
|
+
DEFAULT_BASE_URL = "https://sweetai.tiamatcrypto.com"
|
|
22
|
+
SHOULD_I_PAY_PRICE_USD = 0.02
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class ShouldIPayResult:
|
|
27
|
+
"""Structured result of a pre-payment decision."""
|
|
28
|
+
|
|
29
|
+
agent_id: Optional[int]
|
|
30
|
+
solana_asset: Optional[str]
|
|
31
|
+
amount_usd: float
|
|
32
|
+
payment_required: bool
|
|
33
|
+
price_usd: float
|
|
34
|
+
pay_to: Optional[str]
|
|
35
|
+
networks: list = field(default_factory=list)
|
|
36
|
+
action: Optional[str] = None # PAY / CAUTION / SKIP (after paying)
|
|
37
|
+
confidence: Optional[float] = None
|
|
38
|
+
expected_loss_usd: Optional[float] = None
|
|
39
|
+
raw: Dict[str, Any] = field(default_factory=dict)
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def verdict(self) -> str:
|
|
43
|
+
"""Human/agent-readable one-liner for logs."""
|
|
44
|
+
if self.payment_required:
|
|
45
|
+
nets = ", ".join(self.networks) or "x402 network"
|
|
46
|
+
return (
|
|
47
|
+
f"pay {self.price_usd} USDC on {nets} to {self.pay_to} "
|
|
48
|
+
f"to unlock the {self.amount_usd} USD decision"
|
|
49
|
+
)
|
|
50
|
+
return f"{self.action} (confidence {self.confidence}, expected loss {self.expected_loss_usd} USD)"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class SweetAIFirewall:
|
|
54
|
+
"""Pre-transaction risk firewall powered by SweetAI.
|
|
55
|
+
|
|
56
|
+
Checks the target agent's on-chain reputation (ERC-8004 feedback,
|
|
57
|
+
sybil forensics, liveness SLA) before your agent wires funds.
|
|
58
|
+
|
|
59
|
+
Usage — decision-first:
|
|
60
|
+
fw = SweetAIFirewall()
|
|
61
|
+
result = fw.should_i_pay(agent_id=55985, amount_usd=25)
|
|
62
|
+
print(result.verdict)
|
|
63
|
+
|
|
64
|
+
The x402 payment itself (0.02 USDC per should-i-pay call) is done by
|
|
65
|
+
your agent's wallet using the structured ``accepts`` list returned in
|
|
66
|
+
``result.raw`` — see https://sweetai.tiamatcrypto.com/llms.txt.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, base_url: str = DEFAULT_BASE_URL, timeout: float = 15.0):
|
|
70
|
+
self.base_url = base_url.rstrip("/")
|
|
71
|
+
self._client = httpx.Client(timeout=timeout)
|
|
72
|
+
|
|
73
|
+
# ------------------------------------------------------------------
|
|
74
|
+
# Free surfaces
|
|
75
|
+
# ------------------------------------------------------------------
|
|
76
|
+
def status(self) -> Dict[str, Any]:
|
|
77
|
+
"""Live index stats (agents, feedbacks, chains) — free."""
|
|
78
|
+
return self._client.get(f"{self.base_url}/api/v1/status").json()
|
|
79
|
+
|
|
80
|
+
def network_sybil_overview(self) -> Dict[str, Any]:
|
|
81
|
+
"""Free teaser from the global trust-forensics gate: risk tiers
|
|
82
|
+
across all indexed agents without paying."""
|
|
83
|
+
res = self._client.get(f"{self.base_url}/api/v1/trust-forensics", params={"limit": 1})
|
|
84
|
+
if res.status_code == 402:
|
|
85
|
+
return res.json().get("teaser", {})
|
|
86
|
+
return res.json()
|
|
87
|
+
|
|
88
|
+
def pricing(self) -> Dict[str, Any]:
|
|
89
|
+
"""Current per-endpoint prices."""
|
|
90
|
+
return self._client.get(f"{self.base_url}/api/v1/pricing").json()
|
|
91
|
+
|
|
92
|
+
# ------------------------------------------------------------------
|
|
93
|
+
# Paid: the flagship pre-payment decision
|
|
94
|
+
# ------------------------------------------------------------------
|
|
95
|
+
def should_i_pay(
|
|
96
|
+
self,
|
|
97
|
+
agent_id: Optional[int] = None,
|
|
98
|
+
solana_asset: Optional[str] = None,
|
|
99
|
+
amount_usd: float = 0.05,
|
|
100
|
+
) -> ShouldIPayResult:
|
|
101
|
+
""""Should I pay agent X $N?" — the decision BEFORE the payment.
|
|
102
|
+
|
|
103
|
+
Returns a :class:`ShouldIPayResult`. On first contact the endpoint
|
|
104
|
+
answers HTTP 402 (x402 protocol); the result then carries the
|
|
105
|
+
exact price (0.02 USDC), the payTo address and every accepted
|
|
106
|
+
network so a wallet-holding agent can settle and re-call with the
|
|
107
|
+
X-PAYMENT header.
|
|
108
|
+
"""
|
|
109
|
+
params: Dict[str, Any] = {"amount_usd": amount_usd}
|
|
110
|
+
if agent_id is not None:
|
|
111
|
+
params["agent_id"] = agent_id
|
|
112
|
+
elif solana_asset:
|
|
113
|
+
params["solana_asset"] = solana_asset
|
|
114
|
+
else:
|
|
115
|
+
raise ValueError("pass agent_id (ERC-8004) or solana_asset (Solana pubkey)")
|
|
116
|
+
|
|
117
|
+
res = self._client.get(f"{self.base_url}/api/v1/should-i-pay", params=params)
|
|
118
|
+
out = ShouldIPayResult(
|
|
119
|
+
agent_id=agent_id,
|
|
120
|
+
solana_asset=solana_asset,
|
|
121
|
+
amount_usd=amount_usd,
|
|
122
|
+
payment_required=(res.status_code == 402),
|
|
123
|
+
price_usd=SHOULD_I_PAY_PRICE_USD,
|
|
124
|
+
pay_to=None,
|
|
125
|
+
)
|
|
126
|
+
if res.status_code == 402:
|
|
127
|
+
header = res.headers.get("payment-required") or ""
|
|
128
|
+
try:
|
|
129
|
+
req = json_loads_b64(header)
|
|
130
|
+
accepts = req.get("accepts", [])
|
|
131
|
+
out.pay_to = next((a.get("payTo") for a in accepts if a.get("payTo")), None)
|
|
132
|
+
out.networks = [a.get("network") for a in accepts if a.get("network")]
|
|
133
|
+
out.raw = req
|
|
134
|
+
except Exception: # header missing/malformed — keep 402 info minimal
|
|
135
|
+
out.raw = {"status_code": 402}
|
|
136
|
+
out.raw["teaser"] = _safe_json(res)
|
|
137
|
+
return out
|
|
138
|
+
|
|
139
|
+
body = res.json()
|
|
140
|
+
out.action = body.get("action")
|
|
141
|
+
out.confidence = body.get("confidence")
|
|
142
|
+
out.expected_loss_usd = body.get("expected_loss_usd")
|
|
143
|
+
out.raw = body
|
|
144
|
+
return out
|
|
145
|
+
|
|
146
|
+
def close(self) -> None:
|
|
147
|
+
self._client.close()
|
|
148
|
+
|
|
149
|
+
def __enter__(self) -> "SweetAIFirewall":
|
|
150
|
+
return self
|
|
151
|
+
|
|
152
|
+
def __exit__(self, *exc) -> None:
|
|
153
|
+
self.close()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def json_loads_b64(value: str) -> Dict[str, Any]:
|
|
157
|
+
return dict(__import__("json").loads(base64.b64decode(value)))
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _safe_json(res: httpx.Response) -> Any:
|
|
161
|
+
try:
|
|
162
|
+
return res.json()
|
|
163
|
+
except Exception:
|
|
164
|
+
return {"body": res.text[:500]}
|