open-agentpay 0.2.0__tar.gz → 0.2.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.
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/PKG-INFO +2 -2
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/README.md +1 -1
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/pyproject.toml +1 -1
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/__init__.py +1 -1
- open_agentpay-0.2.2/src/agentpay/client/client.py +170 -0
- open_agentpay-0.2.2/src/agentpay/client/transport.py +491 -0
- {open_agentpay-0.2.0/src/agentpay/protocol → open_agentpay-0.2.2/src/agentpay/core}/codecs.py +10 -1
- {open_agentpay-0.2.0/src/agentpay/protocol → open_agentpay-0.2.2/src/agentpay/core}/models.py +74 -12
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/errors.py +6 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/evaluator.py +65 -6
- open_agentpay-0.2.2/src/agentpay/policy/metered.py +33 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/models.py +11 -2
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/sqlite_engine.py +210 -20
- open_agentpay-0.2.0/src/agentpay/client/client.py +0 -109
- open_agentpay-0.2.0/src/agentpay/client/transport.py +0 -223
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/.gitignore +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/budget/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/client/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/client/errors.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/client/interfaces.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/client/signer.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/core/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/core/errors.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/core/interop.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/core/state.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/evm/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/evm/constants.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/evm/eip3009.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/evm/rpc.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/integrations/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/integrations/langchain/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/integrations/langchain/http.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/integrations/langchain/tool.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/config.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/db.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/policy/interfaces.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/protocol/__init__.py +0 -0
- {open_agentpay-0.2.0/src/agentpay/core → open_agentpay-0.2.2/src/agentpay/protocol}/codecs.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/protocol/errors.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/protocol/interop.py +0 -0
- {open_agentpay-0.2.0/src/agentpay/core → open_agentpay-0.2.2/src/agentpay/protocol}/models.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/protocol/state.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/signer/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/state/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/state/buyer_coordinator.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/state/errors.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/state/guards.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/state/reconciliation.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/testing/__init__.py +0 -0
- {open_agentpay-0.2.0 → open_agentpay-0.2.2}/src/agentpay/testing/mock_seller.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: open-agentpay
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: The Open-Source Payment Infrastructure & Financial Firewall for Autonomous AI Agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/open-agentpay/AgentPay
|
|
6
6
|
Project-URL: Documentation, https://open-agentpay.github.io/AgentPay/
|
|
@@ -67,7 +67,7 @@ Description-Content-Type: text/markdown
|
|
|
67
67
|
|
|
68
68
|
**AgentPay** equips autonomous AI agents with micro-payments (Circle USDC on Arbitrum Sepolia & Base) governed by an in-process, non-custodial **Financial Firewall**. It transparently intercepts `HTTP 402 Payment Required` responses, validates policy limits, and signs off-chain authorizations—protecting agent wallets against runaway loops and LLM hallucinations.
|
|
69
69
|
|
|
70
|
-
> 📦 **Package Name Note**: The canonical PyPI distribution is [`open-agentpay`](https://pypi.org/project/open-agentpay/) (official aliases: `agentpay-core`, `
|
|
70
|
+
> 📦 **Package Name Note**: The canonical PyPI distribution is [`open-agentpay`](https://pypi.org/project/open-agentpay/) (official aliases: `agentpay-core`, `agentpay-firewall`). Regardless of which package you install, you import `agentpay` in Python code.
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
**AgentPay** equips autonomous AI agents with micro-payments (Circle USDC on Arbitrum Sepolia & Base) governed by an in-process, non-custodial **Financial Firewall**. It transparently intercepts `HTTP 402 Payment Required` responses, validates policy limits, and signs off-chain authorizations—protecting agent wallets against runaway loops and LLM hallucinations.
|
|
35
35
|
|
|
36
|
-
> 📦 **Package Name Note**: The canonical PyPI distribution is [`open-agentpay`](https://pypi.org/project/open-agentpay/) (official aliases: `agentpay-core`, `
|
|
36
|
+
> 📦 **Package Name Note**: The canonical PyPI distribution is [`open-agentpay`](https://pypi.org/project/open-agentpay/) (official aliases: `agentpay-core`, `agentpay-firewall`). Regardless of which package you install, you import `agentpay` in Python code.
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AgentPayClient: Drop-in httpx.Client with automatic 402 payment negotiation.
|
|
3
|
+
|
|
4
|
+
Wraps the financial firewall and EIP-712 cryptographic signer to automatically
|
|
5
|
+
satisfy HTTP 402 Payment Required challenges.
|
|
6
|
+
|
|
7
|
+
Note on ``transport=``: unlike a plain httpx.Client, the transport you pass here is the
|
|
8
|
+
INNER transport. It is always wrapped by AgentPayTransport so every request passes the firewall.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import httpx
|
|
17
|
+
|
|
18
|
+
from agentpay.client.interfaces import ISigner
|
|
19
|
+
from agentpay.client.transport import (
|
|
20
|
+
DEFAULT_CREDENTIAL_HEADERS,
|
|
21
|
+
DEFAULT_CREDENTIAL_VALUE_PREFIXES,
|
|
22
|
+
AgentPayTransport,
|
|
23
|
+
AsyncAgentPayTransport,
|
|
24
|
+
CredentialMode,
|
|
25
|
+
)
|
|
26
|
+
from agentpay.policy.interfaces import IPolicyEngine
|
|
27
|
+
|
|
28
|
+
# Client kwargs that configure the default network transport. httpx only applies them when it builds
|
|
29
|
+
# the transport itself; since we always inject ours, they must be forwarded to the inner transport.
|
|
30
|
+
_INNER_PASSTHROUGH = ("verify", "cert", "http1", "http2", "limits", "trust_env")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _inner_transport_kwargs(kwargs: dict[str, Any]) -> dict[str, Any]:
|
|
34
|
+
"""Collect inner-transport settings from client kwargs (mutates ``kwargs``: removes ``proxy``)."""
|
|
35
|
+
if "mounts" in kwargs or "proxies" in kwargs:
|
|
36
|
+
# httpx routes matching URLs to mounted transports BEFORE the default transport,
|
|
37
|
+
# which would skip the payment firewall entirely.
|
|
38
|
+
raise TypeError(
|
|
39
|
+
"AgentPayClient does not support 'mounts'/'proxies': they bypass the payment firewall. "
|
|
40
|
+
"Pass a pre-configured inner transport via transport=... or use proxy=..."
|
|
41
|
+
)
|
|
42
|
+
out = {k: kwargs[k] for k in _INNER_PASSTHROUGH if k in kwargs}
|
|
43
|
+
if "proxy" in kwargs:
|
|
44
|
+
# Left in kwargs, httpx would create a proxy mount that bypasses AgentPayTransport.
|
|
45
|
+
out["proxy"] = kwargs.pop("proxy")
|
|
46
|
+
return out
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class AgentPayClient(httpx.Client):
|
|
50
|
+
"""
|
|
51
|
+
HTTP client for autonomous AI agents with integrated financial firewall.
|
|
52
|
+
|
|
53
|
+
Inherits from httpx.Client: fully compatible with LangChain, LlamaIndex,
|
|
54
|
+
and standard Python HTTP toolchains. Set ``wallet_challenge_mode=True`` when
|
|
55
|
+
sending AgentPay Gateway API-key requests so the first request can receive
|
|
56
|
+
a price challenge before any wallet hold is placed.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
signer: ISigner,
|
|
62
|
+
policy: IPolicyEngine,
|
|
63
|
+
*,
|
|
64
|
+
transport: httpx.BaseTransport | None = None,
|
|
65
|
+
auto_retry_on_402: bool = True,
|
|
66
|
+
raise_on_policy_rejection: bool = False,
|
|
67
|
+
clock: Callable[[], int] | None = None,
|
|
68
|
+
unmetered_credential_policy: CredentialMode = "block",
|
|
69
|
+
credential_headers: tuple[str, ...] = DEFAULT_CREDENTIAL_HEADERS,
|
|
70
|
+
credential_value_prefixes: tuple[str, ...] = DEFAULT_CREDENTIAL_VALUE_PREFIXES,
|
|
71
|
+
estimate_cost: Callable[[httpx.Request], int] | None = None,
|
|
72
|
+
actual_cost: Callable[[httpx.Response], int | None] | None = None,
|
|
73
|
+
credential_ttl_seconds: int = 60,
|
|
74
|
+
wallet_challenge_mode: bool = False,
|
|
75
|
+
**kwargs: Any,
|
|
76
|
+
) -> None:
|
|
77
|
+
inner_kwargs = _inner_transport_kwargs(kwargs)
|
|
78
|
+
|
|
79
|
+
self.signer = signer
|
|
80
|
+
self.policy = policy
|
|
81
|
+
self.auto_retry_on_402 = auto_retry_on_402
|
|
82
|
+
self.raise_on_policy_rejection = raise_on_policy_rejection
|
|
83
|
+
self._clock = clock
|
|
84
|
+
self.unmetered_credential_policy = unmetered_credential_policy
|
|
85
|
+
# Single source of truth, reused by async_client() so both clients behave identically.
|
|
86
|
+
self._agentpay_options: dict[str, Any] = {
|
|
87
|
+
"auto_retry_on_402": auto_retry_on_402,
|
|
88
|
+
"raise_on_policy_rejection": raise_on_policy_rejection,
|
|
89
|
+
"clock": clock,
|
|
90
|
+
"unmetered_credential_policy": unmetered_credential_policy,
|
|
91
|
+
"credential_headers": credential_headers,
|
|
92
|
+
"credential_value_prefixes": credential_value_prefixes,
|
|
93
|
+
"estimate_cost": estimate_cost,
|
|
94
|
+
"actual_cost": actual_cost,
|
|
95
|
+
"credential_ttl_seconds": credential_ttl_seconds,
|
|
96
|
+
"wallet_challenge_mode": wallet_challenge_mode,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
inner = transport if transport is not None else httpx.HTTPTransport(**inner_kwargs)
|
|
100
|
+
agent_transport = AgentPayTransport(inner, signer, policy, **self._agentpay_options)
|
|
101
|
+
super().__init__(transport=agent_transport, **kwargs)
|
|
102
|
+
|
|
103
|
+
def async_client(
|
|
104
|
+
self,
|
|
105
|
+
*,
|
|
106
|
+
transport: httpx.AsyncBaseTransport | None = None,
|
|
107
|
+
**kwargs: Any,
|
|
108
|
+
) -> AsyncAgentPayClient:
|
|
109
|
+
"""Create an AsyncAgentPayClient sharing the same signer, policy and firewall options."""
|
|
110
|
+
options = {**self._agentpay_options, **{k: v for k, v in kwargs.items() if k in self._agentpay_options}}
|
|
111
|
+
client_kwargs = {k: v for k, v in kwargs.items() if k not in self._agentpay_options}
|
|
112
|
+
return AsyncAgentPayClient(
|
|
113
|
+
signer=self.signer,
|
|
114
|
+
policy=self.policy,
|
|
115
|
+
transport=transport,
|
|
116
|
+
**options,
|
|
117
|
+
**client_kwargs,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class AsyncAgentPayClient(httpx.AsyncClient):
|
|
122
|
+
"""
|
|
123
|
+
Asynchronous HTTP client for autonomous AI agents with integrated financial firewall.
|
|
124
|
+
|
|
125
|
+
Inherits from httpx.AsyncClient. Use ``wallet_challenge_mode=True`` for
|
|
126
|
+
AgentPay Gateway API-key requests that must be priced before wallet payment.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
def __init__(
|
|
130
|
+
self,
|
|
131
|
+
signer: ISigner,
|
|
132
|
+
policy: IPolicyEngine,
|
|
133
|
+
*,
|
|
134
|
+
transport: httpx.AsyncBaseTransport | None = None,
|
|
135
|
+
auto_retry_on_402: bool = True,
|
|
136
|
+
raise_on_policy_rejection: bool = False,
|
|
137
|
+
clock: Callable[[], int] | None = None,
|
|
138
|
+
unmetered_credential_policy: CredentialMode = "block",
|
|
139
|
+
credential_headers: tuple[str, ...] = DEFAULT_CREDENTIAL_HEADERS,
|
|
140
|
+
credential_value_prefixes: tuple[str, ...] = DEFAULT_CREDENTIAL_VALUE_PREFIXES,
|
|
141
|
+
estimate_cost: Callable[[httpx.Request], int] | None = None,
|
|
142
|
+
actual_cost: Callable[[httpx.Response], int | None] | None = None,
|
|
143
|
+
credential_ttl_seconds: int = 60,
|
|
144
|
+
wallet_challenge_mode: bool = False,
|
|
145
|
+
**kwargs: Any,
|
|
146
|
+
) -> None:
|
|
147
|
+
inner_kwargs = _inner_transport_kwargs(kwargs)
|
|
148
|
+
|
|
149
|
+
self.signer = signer
|
|
150
|
+
self.policy = policy
|
|
151
|
+
self.auto_retry_on_402 = auto_retry_on_402
|
|
152
|
+
self.raise_on_policy_rejection = raise_on_policy_rejection
|
|
153
|
+
self._clock = clock
|
|
154
|
+
self.unmetered_credential_policy = unmetered_credential_policy
|
|
155
|
+
self._agentpay_options: dict[str, Any] = {
|
|
156
|
+
"auto_retry_on_402": auto_retry_on_402,
|
|
157
|
+
"raise_on_policy_rejection": raise_on_policy_rejection,
|
|
158
|
+
"clock": clock,
|
|
159
|
+
"unmetered_credential_policy": unmetered_credential_policy,
|
|
160
|
+
"credential_headers": credential_headers,
|
|
161
|
+
"credential_value_prefixes": credential_value_prefixes,
|
|
162
|
+
"estimate_cost": estimate_cost,
|
|
163
|
+
"actual_cost": actual_cost,
|
|
164
|
+
"credential_ttl_seconds": credential_ttl_seconds,
|
|
165
|
+
"wallet_challenge_mode": wallet_challenge_mode,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
inner = transport if transport is not None else httpx.AsyncHTTPTransport(**inner_kwargs)
|
|
169
|
+
agent_transport = AsyncAgentPayTransport(inner, signer, policy, **self._agentpay_options)
|
|
170
|
+
super().__init__(transport=agent_transport, **kwargs)
|