onceonly-sdk 2.0.0__tar.gz → 2.0.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.
Files changed (28) hide show
  1. {onceonly_sdk-2.0.0/onceonly_sdk.egg-info → onceonly_sdk-2.0.2}/PKG-INFO +84 -8
  2. onceonly_sdk-2.0.2/README.md +191 -0
  3. onceonly_sdk-2.0.2/onceonly/ai.py +403 -0
  4. onceonly_sdk-2.0.2/onceonly/version.py +1 -0
  5. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2/onceonly_sdk.egg-info}/PKG-INFO +84 -8
  6. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/pyproject.toml +1 -1
  7. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/tests/test_client_behavior.py +34 -0
  8. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/tests/test_integrations.py +41 -0
  9. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/tests/test_parsing.py +27 -0
  10. onceonly_sdk-2.0.0/README.md +0 -115
  11. onceonly_sdk-2.0.0/onceonly/ai.py +0 -195
  12. onceonly_sdk-2.0.0/onceonly/version.py +0 -1
  13. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/LICENSE +0 -0
  14. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/__init__.py +0 -0
  15. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/_http.py +0 -0
  16. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/_util.py +0 -0
  17. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/ai_models.py +0 -0
  18. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/client.py +0 -0
  19. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/decorators.py +0 -0
  20. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/exceptions.py +0 -0
  21. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/integrations/__init__.py +0 -0
  22. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/integrations/langchain.py +0 -0
  23. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly/models.py +0 -0
  24. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly_sdk.egg-info/SOURCES.txt +0 -0
  25. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly_sdk.egg-info/dependency_links.txt +0 -0
  26. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly_sdk.egg-info/requires.txt +0 -0
  27. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/onceonly_sdk.egg-info/top_level.txt +0 -0
  28. {onceonly_sdk-2.0.0 → onceonly_sdk-2.0.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onceonly-sdk
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Python SDK for OnceOnly idempotency API
5
5
  Author-email: OnceOnly <support@onceonly.tech>
6
6
  License: MIT
@@ -31,9 +31,27 @@ OnceOnly is a high-performance Python SDK that ensures **exactly-once execution*
31
31
  It prevents duplicate actions (payments, emails, tool calls) in unstable environments like
32
32
  AI agents, webhooks, retries, or background workers.
33
33
 
34
+
34
35
  Website: https://onceonly.tech/ai/
35
36
  Documentation: https://onceonly.tech/docs/
36
37
 
38
+ [![PyPI version](https://img.shields.io/pypi/v/onceonly-sdk.svg)](https://pypi.org/project/onceonly-sdk/)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
40
+ ---
41
+
42
+ ## Why duplicates happen
43
+
44
+ Duplicate actions are common in modern systems because:
45
+ - AI agents retry or re-plan tool calls
46
+ - Webhooks are delivered more than once
47
+ - Workers crash after side-effects
48
+ - Distributed systems replay events
49
+
50
+ Without an idempotency layer, the same action may run multiple times.
51
+
52
+ OnceOnly is designed to guard side-effects in non-deterministic AI agent loops,
53
+ where the same tool call may be executed multiple times.
54
+
37
55
  ---
38
56
 
39
57
  ## Features
@@ -41,9 +59,21 @@ Documentation: https://onceonly.tech/docs/
41
59
  - Sync + Async client (httpx-based)
42
60
  - Fail-open mode for production safety
43
61
  - Stable idempotency keys (supports Pydantic & dataclasses)
44
- - Decorator for zero-boilerplate usage
62
+ - Decorators for zero-boilerplate usage
63
+ - Native AI API (long-running jobs, local side-effects)
45
64
  - Optional AI / LangChain integrations
46
65
 
66
+ ---
67
+
68
+ ## FAQ
69
+
70
+ **Does this prevent duplicate payments or emails?**
71
+ Yes. OnceOnly guarantees exactly-once execution for side-effects.
72
+
73
+ **Is this a retry library?**
74
+ No. Retries still happen — OnceOnly ensures the action itself runs only once.
75
+
76
+
47
77
  ---
48
78
 
49
79
  ## Installation
@@ -60,7 +90,7 @@ pip install "onceonly-sdk[langchain]"
60
90
 
61
91
  ---
62
92
 
63
- ## Quick Start
93
+ ## Quick Start (Webhooks / Automations)
64
94
 
65
95
  ```python
66
96
  from onceonly import OnceOnly
@@ -78,11 +108,54 @@ else:
78
108
  print("First execution")
79
109
  ```
80
110
 
111
+ Use `check_lock()` for:
112
+ - Webhooks
113
+ - Make / Zapier scenarios
114
+ - Cron jobs
115
+ - Distributed workers
116
+
81
117
  ---
82
118
 
83
- ## AI Agents / LangChain Integration 🤖
119
+ ## AI Jobs (Server-side)
84
120
 
85
- OnceOnly integrates cleanly with AI-agent frameworks like LangChain.
121
+ Use the AI API for long-running or asynchronous jobs.
122
+
123
+ ```python
124
+ result = client.ai.run_and_wait(
125
+ key="ai:job:daily_summary:2026-01-09",
126
+ metadata={"task": "daily_summary", "model": "gpt-4.1"},
127
+ timeout=60,
128
+ )
129
+
130
+ print(result.status)
131
+ print(result.result)
132
+ ```
133
+
134
+ - Charged **once per key**
135
+ - Polling is free
136
+ - Safe across retries and restarts
137
+
138
+ ---
139
+
140
+ ## AI Agents / Local Side-Effects
141
+
142
+ Use the AI Lease API when your code performs the side-effect locally
143
+ (payments, emails, webhooks) but still needs exactly-once guarantees.
144
+
145
+ ```python
146
+ lease = client.ai.lease(key="ai:agent:charge:user_42:invoice_100", ttl=300)
147
+
148
+ if lease["status"] == "acquired":
149
+ try:
150
+ do_side_effect()
151
+ client.ai.complete(key=KEY, lease_id=lease["lease_id"], result={"ok": True})
152
+ except Exception:
153
+ client.ai.fail(key=KEY, lease_id=lease["lease_id"], error_code="failed")
154
+ ```
155
+
156
+ ---
157
+
158
+ ## LangChain Integration 🤖
86
159
 
87
160
  ```python
88
161
  from onceonly.integrations.langchain import make_idempotent_tool
@@ -94,11 +167,14 @@ tool = make_idempotent_tool(
94
167
  )
95
168
  ```
96
169
 
97
- Repeated tool calls with the same inputs will execute **exactly once**, even across retries or agent restarts.
170
+ Repeated tool calls with the same inputs will execute **exactly once**,
171
+ even across retries or agent restarts.
172
+
173
+ See `examples/ai/` for canonical patterns.
98
174
 
99
175
  ---
100
176
 
101
- ## Decorator
177
+ ## Decorators
102
178
 
103
179
  ```python
104
180
  from onceonly.decorators import idempotent
@@ -108,7 +184,7 @@ def process_order(order_id):
108
184
  ...
109
185
  ```
110
186
 
111
- Idempotency keys are generated automatically and are stable across restarts.
187
+ Idempotency keys are generated automatically and remain stable across restarts.
112
188
 
113
189
  ---
114
190
 
@@ -0,0 +1,191 @@
1
+ # OnceOnly Python SDK
2
+
3
+ **The Idempotency Layer for AI Agents, Webhooks, and Distributed Systems.**
4
+
5
+ OnceOnly is a high-performance Python SDK that ensures **exactly-once execution**.
6
+ It prevents duplicate actions (payments, emails, tool calls) in unstable environments like
7
+ AI agents, webhooks, retries, or background workers.
8
+
9
+
10
+ Website: https://onceonly.tech/ai/
11
+ Documentation: https://onceonly.tech/docs/
12
+
13
+ [![PyPI version](https://img.shields.io/pypi/v/onceonly-sdk.svg)](https://pypi.org/project/onceonly-sdk/)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
15
+ ---
16
+
17
+ ## Why duplicates happen
18
+
19
+ Duplicate actions are common in modern systems because:
20
+ - AI agents retry or re-plan tool calls
21
+ - Webhooks are delivered more than once
22
+ - Workers crash after side-effects
23
+ - Distributed systems replay events
24
+
25
+ Without an idempotency layer, the same action may run multiple times.
26
+
27
+ OnceOnly is designed to guard side-effects in non-deterministic AI agent loops,
28
+ where the same tool call may be executed multiple times.
29
+
30
+ ---
31
+
32
+ ## Features
33
+
34
+ - Sync + Async client (httpx-based)
35
+ - Fail-open mode for production safety
36
+ - Stable idempotency keys (supports Pydantic & dataclasses)
37
+ - Decorators for zero-boilerplate usage
38
+ - Native AI API (long-running jobs, local side-effects)
39
+ - Optional AI / LangChain integrations
40
+
41
+ ---
42
+
43
+ ## FAQ
44
+
45
+ **Does this prevent duplicate payments or emails?**
46
+ Yes. OnceOnly guarantees exactly-once execution for side-effects.
47
+
48
+ **Is this a retry library?**
49
+ No. Retries still happen — OnceOnly ensures the action itself runs only once.
50
+
51
+
52
+ ---
53
+
54
+ ## Installation
55
+
56
+ ```bash
57
+ pip install onceonly-sdk
58
+ ```
59
+
60
+ ### With LangChain support included:
61
+
62
+ ```bash
63
+ pip install "onceonly-sdk[langchain]"
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Quick Start (Webhooks / Automations)
69
+
70
+ ```python
71
+ from onceonly import OnceOnly
72
+
73
+ client = OnceOnly(
74
+ api_key="once_live_...",
75
+ fail_open=True # default: continues if API is down
76
+ )
77
+
78
+ res = client.check_lock(key="order:123", ttl=300)
79
+
80
+ if res.duplicate:
81
+ print("Duplicate blocked")
82
+ else:
83
+ print("First execution")
84
+ ```
85
+
86
+ Use `check_lock()` for:
87
+ - Webhooks
88
+ - Make / Zapier scenarios
89
+ - Cron jobs
90
+ - Distributed workers
91
+
92
+ ---
93
+
94
+ ## AI Jobs (Server-side)
95
+
96
+ Use the AI API for long-running or asynchronous jobs.
97
+
98
+ ```python
99
+ result = client.ai.run_and_wait(
100
+ key="ai:job:daily_summary:2026-01-09",
101
+ metadata={"task": "daily_summary", "model": "gpt-4.1"},
102
+ timeout=60,
103
+ )
104
+
105
+ print(result.status)
106
+ print(result.result)
107
+ ```
108
+
109
+ - Charged **once per key**
110
+ - Polling is free
111
+ - Safe across retries and restarts
112
+
113
+ ---
114
+
115
+ ## AI Agents / Local Side-Effects
116
+
117
+ Use the AI Lease API when your code performs the side-effect locally
118
+ (payments, emails, webhooks) but still needs exactly-once guarantees.
119
+
120
+ ```python
121
+ lease = client.ai.lease(key="ai:agent:charge:user_42:invoice_100", ttl=300)
122
+
123
+ if lease["status"] == "acquired":
124
+ try:
125
+ do_side_effect()
126
+ client.ai.complete(key=KEY, lease_id=lease["lease_id"], result={"ok": True})
127
+ except Exception:
128
+ client.ai.fail(key=KEY, lease_id=lease["lease_id"], error_code="failed")
129
+ ```
130
+
131
+ ---
132
+
133
+ ## LangChain Integration 🤖
134
+
135
+ ```python
136
+ from onceonly.integrations.langchain import make_idempotent_tool
137
+
138
+ tool = make_idempotent_tool(
139
+ original_tool,
140
+ client=client,
141
+ key_prefix="agent:tool"
142
+ )
143
+ ```
144
+
145
+ Repeated tool calls with the same inputs will execute **exactly once**,
146
+ even across retries or agent restarts.
147
+
148
+ See `examples/ai/` for canonical patterns.
149
+
150
+ ---
151
+
152
+ ## Decorators
153
+
154
+ ```python
155
+ from onceonly.decorators import idempotent
156
+
157
+ @idempotent(client, ttl=3600)
158
+ def process_order(order_id):
159
+ ...
160
+ ```
161
+
162
+ Idempotency keys are generated automatically and remain stable across restarts.
163
+
164
+ ---
165
+
166
+ ## Fail-Open Mode
167
+
168
+ Fail-open is enabled by default.
169
+
170
+ Network errors, timeouts, or server errors (5xx) will **not break your application**.
171
+ The SDK will allow execution to continue safely.
172
+
173
+ Fail-open never applies to:
174
+ - Auth errors (401 / 403)
175
+ - Plan limits (402)
176
+ - Validation errors (422)
177
+ - Rate limits (429)
178
+
179
+ ---
180
+
181
+ ## Support
182
+
183
+ Need help?
184
+ Email: support@onceonly.tech
185
+ Or open an issue on GitHub.
186
+
187
+ ---
188
+
189
+ ## License
190
+
191
+ MIT