@paygentic/wrap 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +266 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +16 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/schema.d.ts +6427 -0
- package/dist/api/schema.d.ts.map +1 -0
- package/dist/api/schema.js +6 -0
- package/dist/api/schema.js.map +1 -0
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +262 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/customer.d.ts +108 -0
- package/dist/customer.d.ts.map +1 -0
- package/dist/customer.js +7 -0
- package/dist/customer.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/logCosts.d.ts +12 -0
- package/dist/logCosts.d.ts.map +1 -0
- package/dist/logCosts.js +61 -0
- package/dist/logCosts.js.map +1 -0
- package/dist/plan.d.ts +27 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +279 -0
- package/dist/plan.js.map +1 -0
- package/dist/subscription.d.ts +52 -0
- package/dist/subscription.d.ts.map +1 -0
- package/dist/subscription.js +106 -0
- package/dist/subscription.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Paygentic
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# Wrap SDK
|
|
2
|
+
|
|
3
|
+
Wrap Claude agent queries with automatic payment tracking and usage metering.
|
|
4
|
+
|
|
5
|
+
**Paygentic Platform:** [Production](https://platform.paygentic.io) | [Sandbox](https://platform.sandbox.paygentic.io)
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { createWrapClient } from "@paygentic/wrap";
|
|
11
|
+
|
|
12
|
+
const client = createWrapClient();
|
|
13
|
+
const plan = await client.plans.init();
|
|
14
|
+
const query = plan.wrap("customer_123");
|
|
15
|
+
|
|
16
|
+
// wrapped query supports all claude agent sdk options
|
|
17
|
+
const response = await query({
|
|
18
|
+
model: "claude-sonnet-4-20250514",
|
|
19
|
+
prompt: "Hello, world!",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
for await (const message of response) {
|
|
23
|
+
// Process messages as usual
|
|
24
|
+
// Usage is automatically tracked on completion
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @paygentic/wrap
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## CLI Setup
|
|
35
|
+
|
|
36
|
+
The package includes an interactive setup command that creates the necessary Paygentic resources (product, billable metric, price, and plan) for your agent:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx @paygentic/wrap setup
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### What It Does
|
|
43
|
+
|
|
44
|
+
The setup wizard will:
|
|
45
|
+
|
|
46
|
+
1. **Prompt for configuration:**
|
|
47
|
+
- Environment (`sandbox` or `prod`)
|
|
48
|
+
- API Key (from [Paygentic Platform](https://platform.paygentic.io/merchant/developer/apikeys))
|
|
49
|
+
- Merchant ID (from [Organization Settings](https://platform.paygentic.io/merchant/settings/organization))
|
|
50
|
+
- Agent name (used for product naming)
|
|
51
|
+
- Payment type (`instant` or `post-paid`)
|
|
52
|
+
- Max expected usage per query (USD)
|
|
53
|
+
- Margin percentage (markup on usage costs)
|
|
54
|
+
|
|
55
|
+
2. **Create Paygentic resources:**
|
|
56
|
+
- Product for your agent
|
|
57
|
+
- Billable metric for tracking usage
|
|
58
|
+
- Price with your configured margin
|
|
59
|
+
- Plan linking everything together
|
|
60
|
+
|
|
61
|
+
3. **Output environment variables** to add to your `.env` file
|
|
62
|
+
|
|
63
|
+
### Example Session
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
=== Paygentic Agent Billing Setup ===
|
|
67
|
+
|
|
68
|
+
Environment (sandbox/prod) [sandbox]: sandbox
|
|
69
|
+
Get your API key from: https://platform.sandbox.paygentic.io/merchant/developer/apikeys
|
|
70
|
+
API Key: pk_sandbox_xxxxx
|
|
71
|
+
Merchant ID: mer_xxxxx
|
|
72
|
+
Agent Name: My AI Assistant
|
|
73
|
+
Payment Type (instant/post-paid): instant
|
|
74
|
+
Max expected usage per query (USD) [2.00]: 2.00
|
|
75
|
+
Margin percentage [10]: 15
|
|
76
|
+
|
|
77
|
+
--- Creating Paygentic resources ---
|
|
78
|
+
|
|
79
|
+
Creating product...
|
|
80
|
+
Creating billable metric...
|
|
81
|
+
Creating price...
|
|
82
|
+
Creating plan...
|
|
83
|
+
|
|
84
|
+
=== Setup complete! ===
|
|
85
|
+
|
|
86
|
+
Add these to your .env file:
|
|
87
|
+
|
|
88
|
+
PAYGENTIC_WRAP_ENV=sandbox
|
|
89
|
+
PAYGENTIC_WRAP_API_KEY=pk_sandbox_xxxxx
|
|
90
|
+
PAYGENTIC_WRAP_MERCHANT_ID=mer_xxxxx
|
|
91
|
+
PAYGENTIC_WRAP_PRODUCT_ID=prod_xxxxx
|
|
92
|
+
PAYGENTIC_WRAP_PLAN_ID=plan_xxxxx
|
|
93
|
+
PAYGENTIC_WRAP_PRICE_ID=price_xxxxx
|
|
94
|
+
PAYGENTIC_WRAP_BILLABLE_METRIC_ID=bm_xxxxx
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Environment Variables
|
|
98
|
+
|
|
99
|
+
The SDK reads these environment variables as defaults:
|
|
100
|
+
|
|
101
|
+
| Variable | Description | Required |
|
|
102
|
+
|----------|-------------|----------|
|
|
103
|
+
| `PAYGENTIC_WRAP_API_KEY` | Your Paygentic API key | Yes (or pass `apiKey` option) |
|
|
104
|
+
| `PAYGENTIC_WRAP_ENV` | Environment: `prod` or `sandbox` | No (defaults to `prod`) |
|
|
105
|
+
| `PAYGENTIC_WRAP_MERCHANT_ID` | Your merchant ID | For setup script |
|
|
106
|
+
| `PAYGENTIC_WRAP_PLAN_ID` | Your plan ID | For your app |
|
|
107
|
+
| `PAYGENTIC_WRAP_PRICE_ID` | Your price ID | For your app |
|
|
108
|
+
| `PAYGENTIC_WRAP_PRODUCT_ID` | Your product ID | For reference |
|
|
109
|
+
| `PAYGENTIC_WRAP_BILLABLE_METRIC_ID` | Your billable metric ID | For reference |
|
|
110
|
+
|
|
111
|
+
Run `npx @paygentic/wrap setup` to create these resources and get the environment variables.
|
|
112
|
+
|
|
113
|
+
## How It Works
|
|
114
|
+
|
|
115
|
+
When you call `wrap`, the SDK:
|
|
116
|
+
|
|
117
|
+
1. Verifies the customer has an active subscription
|
|
118
|
+
2. Sets a safe budget limit (90% of maxPrice or maxPrice - $0.10)
|
|
119
|
+
3. Reserves funds for instant payments
|
|
120
|
+
4. Tracks usage and creates billing/payment events on completion
|
|
121
|
+
5. Handles overages by splitting into multiple events if needed
|
|
122
|
+
|
|
123
|
+
## Pricing Models
|
|
124
|
+
|
|
125
|
+
### Dynamic Pricing
|
|
126
|
+
|
|
127
|
+
Only pass through usage cost to end user:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Price config: maxPrice >= $0.20
|
|
131
|
+
const plan = await client.plans.init({
|
|
132
|
+
planId: "plan_abc123",
|
|
133
|
+
priceId: "price_dynamic",
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Percentage Pricing
|
|
138
|
+
|
|
139
|
+
Apply a markup to usage cost:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Price config: percentage, minCharge, maxCharge (maxCharge >= $0.20)
|
|
143
|
+
// Plan and price id default to PAYGENTIC_WRAP_PLAN_ID resp PAYGENTIC_WRAP_PRICE_ID
|
|
144
|
+
const plan = await client.plans.init({
|
|
145
|
+
planId: "plan_abc123",
|
|
146
|
+
priceId: "price_percentage",
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Subscriptions
|
|
151
|
+
|
|
152
|
+
### Create a Customer and Subscription
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const result = await client.subscriptions.create({
|
|
156
|
+
customer: {
|
|
157
|
+
name: "Example Inc",
|
|
158
|
+
email: "billing@example.com",
|
|
159
|
+
address: {
|
|
160
|
+
line1: "123 Main St",
|
|
161
|
+
city: "San Francisco",
|
|
162
|
+
state: "CA",
|
|
163
|
+
postalCode: "94105",
|
|
164
|
+
country: "US",
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
minWalletAmount: "20.00",
|
|
168
|
+
redirectUrls: {
|
|
169
|
+
onSuccess: "https://example.com/success",
|
|
170
|
+
onFailure: "https://example.com/failure",
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const { customerId, subscriptionDetail } = result;
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Get Customer Portal URL
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const portal = await client.subscriptions.portal(subscriptionId);
|
|
181
|
+
// portal.url - redirect customers here to manage their subscription
|
|
182
|
+
// portal.expiresAt - URL expiration time
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Find Customer by Email
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const customerId = await client.subscriptions.findCustomer("billing@example.com");
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Payment Terms
|
|
192
|
+
|
|
193
|
+
- **Pre-paid** (default): Creates an entitlement before the query runs
|
|
194
|
+
- **In-arrears**: Records usage after the query completes
|
|
195
|
+
|
|
196
|
+
## Error Handling
|
|
197
|
+
|
|
198
|
+
### Insufficient Funds
|
|
199
|
+
|
|
200
|
+
When a customer doesn't have enough balance to process a query, the SDK throws an `InsufficientFundsError` with a portal URL so they can top up:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { createWrapClient, InsufficientFundsError } from "@paygentic/wrap";
|
|
204
|
+
|
|
205
|
+
const client = createWrapClient();
|
|
206
|
+
const plan = await client.plans.init();
|
|
207
|
+
const query = plan.wrap("customer_123");
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
const response = await query({ model: "claude-sonnet-4-20250514", prompt: "Hello" });
|
|
211
|
+
for await (const message of response) {
|
|
212
|
+
// Process messages
|
|
213
|
+
}
|
|
214
|
+
} catch (error) {
|
|
215
|
+
if (error instanceof InsufficientFundsError) {
|
|
216
|
+
console.log("Please top up your balance:", error.portalUrl);
|
|
217
|
+
console.log("Link expires at:", error.portalExpiresAt);
|
|
218
|
+
console.log("Subscription ID:", error.subscriptionId);
|
|
219
|
+
// Redirect customer to error.portalUrl to add funds
|
|
220
|
+
} else {
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The `InsufficientFundsError` includes:
|
|
227
|
+
|
|
228
|
+
- `portalUrl` - URL where the customer can add funds to their wallet
|
|
229
|
+
- `portalExpiresAt` - When the portal URL expires (ISO timestamp)
|
|
230
|
+
- `subscriptionId` - The subscription that needs funding
|
|
231
|
+
|
|
232
|
+
### Query Stopped Due to Budget Limit
|
|
233
|
+
|
|
234
|
+
The SDK automatically sets a budget limit based on your pricing config to protect against runaway costs. When a query exceeds this limit, the agent stops and the result message has `subtype: "error_max_budget_usd"`.
|
|
235
|
+
|
|
236
|
+
You can resume the query by passing the `session_id` in the `options.resume` field:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
let sessionId: string | undefined;
|
|
240
|
+
|
|
241
|
+
const response = await query({ model: "claude-sonnet-4-20250514", prompt: "Complex task" });
|
|
242
|
+
|
|
243
|
+
for await (const message of response) {
|
|
244
|
+
if (message.type === "result") {
|
|
245
|
+
sessionId = message.session_id;
|
|
246
|
+
|
|
247
|
+
if (message.subtype === "error_max_budget_usd") {
|
|
248
|
+
console.log("Query stopped due to budget limit");
|
|
249
|
+
console.log("Cost incurred:", message.total_cost_usd);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Resume the query if it stopped due to budget limit
|
|
255
|
+
if (sessionId) {
|
|
256
|
+
const continuation = await query({
|
|
257
|
+
model: "claude-sonnet-4-20250514",
|
|
258
|
+
prompt: "Please continue",
|
|
259
|
+
options: { resume: sessionId },
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
for await (const message of continuation) {
|
|
263
|
+
// Billing is handled automatically for the continuation
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAO3C,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAe,gEAQnE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import createClient from "openapi-fetch";
|
|
2
|
+
const baseUrlMap = {
|
|
3
|
+
prod: 'https://api.paygentic.io',
|
|
4
|
+
sandbox: 'https://api.sandbox.paygentic.io',
|
|
5
|
+
local: 'http://localhost:8200',
|
|
6
|
+
};
|
|
7
|
+
export function createApiClient(apiKey, env = 'prod') {
|
|
8
|
+
const baseUrl = baseUrlMap[env] || baseUrlMap.prod;
|
|
9
|
+
return createClient({
|
|
10
|
+
baseUrl,
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${apiKey}`,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAIzC,MAAM,UAAU,GAA2B;IACzC,IAAI,EAAE,0BAA0B;IAChC,OAAO,EAAE,kCAAkC;IAC3C,KAAK,EAAE,uBAAuB;CAC/B,CAAA;AAED,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,MAAc,MAAM;IAClE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;IACnD,OAAO,YAAY,CAAQ;QACzB,OAAO;QACP,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;SAClC;KACF,CAAC,CAAC;AACL,CAAC"}
|