@apicity/cost 0.2.0-alpha.1 → 0.2.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/README.md +144 -147
- package/dist/src/cost.d.ts +1 -1
- package/dist/src/cost.d.ts.map +1 -1
- package/dist/src/cost.js +1 -1
- package/dist/src/cost.js.map +1 -1
- package/dist/src/index.d.ts +6 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/paid-endpoints.d.ts +0 -64
- package/dist/src/paid-endpoints.d.ts.map +1 -1
- package/dist/src/paid-endpoints.js +9 -113
- package/dist/src/paid-endpoints.js.map +1 -1
- package/dist/src/paygate-cli.d.ts +1 -17
- package/dist/src/paygate-cli.d.ts.map +1 -1
- package/dist/src/paygate-cli.js +23 -103
- package/dist/src/paygate-cli.js.map +1 -1
- package/dist/src/paygate.d.ts +99 -19
- package/dist/src/paygate.d.ts.map +1 -1
- package/dist/src/paygate.js +180 -122
- package/dist/src/paygate.js.map +1 -1
- package/dist/src/with-paid-gate.d.ts +27 -0
- package/dist/src/with-paid-gate.d.ts.map +1 -0
- package/dist/src/with-paid-gate.js +91 -0
- package/dist/src/with-paid-gate.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -149,18 +149,22 @@ The cost package maintains a small, explicit **paid-endpoint registry**.
|
|
|
149
149
|
Endpoints that are **not** in the registry are assumed free and require no
|
|
150
150
|
caller changes.
|
|
151
151
|
|
|
152
|
-
Paid endpoints require a **
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
Paid endpoints require a **single-use OTP** (one-time password) minted from a
|
|
153
|
+
shared **HMAC secret**. The gate is fail-closed and does **no** cost
|
|
154
|
+
estimation — it is pure authorization: a paid call cannot fire unless the
|
|
155
|
+
provider was constructed with the secret **and** the caller presents a valid,
|
|
156
|
+
request-bound OTP. The autonomous caller never holds the secret, so it cannot
|
|
157
|
+
self-approve; only the human or the code client that holds the secret can mint.
|
|
158
|
+
|
|
159
|
+
There are **no environment variables and no key files** — the secret is passed
|
|
160
|
+
in via factory options (or the MCP server's `--paygate-secret-file`).
|
|
156
161
|
|
|
157
162
|
### Registry model
|
|
158
163
|
|
|
159
164
|
- `PAID_ENDPOINTS` is the canonical list. Every entry is an exact triple of
|
|
160
165
|
`(provider, method, dotPath)` — there is no regex, prefix, wildcard, or
|
|
161
166
|
inferred matching.
|
|
162
|
-
- Unlisted endpoints are free
|
|
163
|
-
pay gate configuration.
|
|
167
|
+
- Unlisted endpoints are free and pass through without OTP or configuration.
|
|
164
168
|
- Listed endpoints block unless a valid OTP is supplied.
|
|
165
169
|
|
|
166
170
|
### Token format
|
|
@@ -168,69 +172,80 @@ operator-held Ed25519 key.
|
|
|
168
172
|
OTP tokens are a dependency-free compact envelope:
|
|
169
173
|
|
|
170
174
|
```
|
|
171
|
-
<base64url(payloadJson)>.<base64url(
|
|
175
|
+
<base64url(payloadJson)>.<base64url(HMAC-SHA256(payloadSegment, secret))>
|
|
172
176
|
```
|
|
173
177
|
|
|
174
|
-
The
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
Payload schema:
|
|
178
|
+
The signature is HMAC-SHA256 over the exact base64url payload segment bytes,
|
|
179
|
+
verified in constant time. Payload schema:
|
|
178
180
|
|
|
179
181
|
```ts
|
|
180
182
|
interface PayGateOtpPayload {
|
|
181
|
-
v: 1;
|
|
182
|
-
jti: string;
|
|
183
|
-
provider: string;
|
|
184
|
-
method: string;
|
|
185
|
-
dotPath: string;
|
|
183
|
+
v: 1; // version
|
|
184
|
+
jti: string; // random 128-bit hex (unique token id)
|
|
185
|
+
provider: string; // e.g. "kie"
|
|
186
|
+
method: string; // e.g. "POST"
|
|
187
|
+
dotPath: string; // e.g. "api.v1.jobs.createTask"
|
|
186
188
|
requestHash: `sha256:${string}`; // sha256 of canonical request JSON
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
exp: number; // expiration unix seconds
|
|
189
|
+
iat: number; // issued-at unix seconds
|
|
190
|
+
exp: number; // expiration unix seconds
|
|
190
191
|
}
|
|
191
192
|
```
|
|
192
193
|
|
|
193
|
-
|
|
194
|
-
payload. Object keys are sorted recursively; array order is preserved.
|
|
195
|
-
Non-JSON payload values must fail closed.
|
|
194
|
+
### Configuration
|
|
196
195
|
|
|
197
|
-
|
|
196
|
+
The code client supplies a `PayGateConfig` via factory options:
|
|
198
197
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
```ts
|
|
199
|
+
interface PayGateConfig {
|
|
200
|
+
secret: string; // shared HMAC secret (the code client holds it)
|
|
201
|
+
replayStore?: ReplayStore; // defaults to an in-process Set, per provider instance
|
|
202
|
+
now?: () => number; // clock injection for tests; defaults to Date.now
|
|
203
|
+
}
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
interface ReplayStore {
|
|
206
|
+
has(jti: string): boolean;
|
|
207
|
+
add(jti: string): void;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
206
210
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
| `APICITY_PAYGATE_PRIVATE_KEY_PATH` | Yes | Path to an Ed25519 private key PEM file. Used by the `apicity-paygate` CLI to sign OTPs. |
|
|
211
|
+
```ts
|
|
212
|
+
import { createKie } from "@apicity/kie";
|
|
210
213
|
|
|
211
|
-
|
|
214
|
+
const provider = createKie({
|
|
215
|
+
apiKey: process.env.KIE_API_KEY!,
|
|
216
|
+
paygate: { secret: loadSecret() }, // from your secret manager / config
|
|
217
|
+
});
|
|
218
|
+
```
|
|
212
219
|
|
|
213
|
-
|
|
220
|
+
### Minting OTPs
|
|
214
221
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
3. Reject non-JSON values (functions, undefined, circular references, etc.).
|
|
222
|
+
`mintOtp` is pure and env-free — the secret is passed explicitly and the OTP
|
|
223
|
+
binds to the exact request via its canonical hash:
|
|
218
224
|
|
|
219
|
-
|
|
220
|
-
|
|
225
|
+
```ts
|
|
226
|
+
import { mintOtp } from "@apicity/cost";
|
|
221
227
|
|
|
222
|
-
|
|
228
|
+
const otp = mintOtp(secret, {
|
|
229
|
+
dotPath: "api.v1.jobs.createTask", // provider/method resolved from the registry
|
|
230
|
+
request: payload, // bound by canonical hash
|
|
231
|
+
ttl: "10m", // seconds or "10m" / "1h" / "1d"; defaults to 10m
|
|
232
|
+
});
|
|
233
|
+
```
|
|
223
234
|
|
|
224
|
-
|
|
225
|
-
attacks. The default ledger path:
|
|
235
|
+
### Request canonicalization
|
|
226
236
|
|
|
227
|
-
|
|
228
|
-
|
|
237
|
+
Before hashing, the request payload is canonicalized: serialized to JSON with
|
|
238
|
+
**sorted object keys** (recursive), preserving array order, rejecting non-JSON
|
|
239
|
+
values (functions, undefined, circular references). The canonical string is
|
|
240
|
+
SHA-256 hashed and prefixed with `sha256:`. Change any byte of the request and
|
|
241
|
+
verification fails.
|
|
229
242
|
|
|
230
|
-
|
|
243
|
+
### Replay protection
|
|
231
244
|
|
|
232
|
-
|
|
233
|
-
|
|
245
|
+
Each OTP `jti` is single-use. The default `ReplayStore` is an in-process Set
|
|
246
|
+
scoped to one provider instance (no files, no `XDG_STATE_HOME`). Pass a custom
|
|
247
|
+
`replayStore` for cross-process or persistent protection. The `jti` is consumed
|
|
248
|
+
**before** dispatch — see [Retry semantics](#retry-semantics).
|
|
234
249
|
|
|
235
250
|
### Public interface
|
|
236
251
|
|
|
@@ -245,153 +260,135 @@ async function dispatchWithPaidGate<T>(
|
|
|
245
260
|
dotPath: string,
|
|
246
261
|
payload: Record<string, unknown>,
|
|
247
262
|
approval: PayGateApproval | undefined,
|
|
248
|
-
dispatch: () => Promise<T
|
|
263
|
+
dispatch: () => Promise<T>,
|
|
264
|
+
config?: PayGateConfig
|
|
249
265
|
): Promise<T>;
|
|
250
266
|
```
|
|
251
267
|
|
|
252
|
-
Paid endpoint APIs
|
|
268
|
+
Paid endpoint APIs accept the approval as a second options object:
|
|
253
269
|
|
|
254
270
|
```ts
|
|
255
|
-
import { kie } from "@apicity/kie";
|
|
256
|
-
|
|
257
|
-
const provider = kie({ apiKey: process.env.KIE_API_KEY! });
|
|
258
|
-
|
|
259
271
|
const task = await provider.post.api.v1.jobs.createTask(
|
|
260
|
-
{
|
|
261
|
-
|
|
262
|
-
input: { prompt: "...", duration: "5", aspect_ratio: "16:9" },
|
|
263
|
-
},
|
|
264
|
-
{ otp: "eyJ2IjoxLCJqdGkiOi4uLn0.uK2J9..." }
|
|
272
|
+
{ model: "kling-3.0/video", input: { prompt: "...", duration: "5" } },
|
|
273
|
+
{ otp }
|
|
265
274
|
);
|
|
266
275
|
```
|
|
267
276
|
|
|
268
277
|
### Guard behavior
|
|
269
278
|
|
|
270
|
-
1. **Preflight** —
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
throws `PayGateError
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
7. **Estimate** — the package computes a local cost estimate from the payload.
|
|
285
|
-
8. **Bound check** — if the estimate exceeds `maxSpendUsd`, or if the cost
|
|
286
|
-
cannot be estimated (unknown model, missing fields), the call throws
|
|
287
|
-
`SpendBoundError`.
|
|
288
|
-
9. **Consume** — the `jti` is appended to the replay ledger.
|
|
289
|
-
10. **Dispatch** — only when all checks pass does the actual HTTP request fire.
|
|
279
|
+
1. **Preflight** — if the endpoint is not in `PAID_ENDPOINTS`, dispatch runs
|
|
280
|
+
immediately.
|
|
281
|
+
2. **Configuration** — a paid endpoint with no `paygate.secret` throws
|
|
282
|
+
`PayGateError` (`paygate-not-configured`).
|
|
283
|
+
3. **OTP presence** — paid endpoints require `approval.otp`; if omitted the call
|
|
284
|
+
throws `PayGateError` (`otp-missing`).
|
|
285
|
+
4. **Signature** — the payload segment's HMAC is verified (constant-time)
|
|
286
|
+
against the secret; mismatch throws `PayGateError` (`otp-invalid-signature`).
|
|
287
|
+
5. **Expiration** — `exp` in the past throws `PayGateError` (`otp-expired`).
|
|
288
|
+
6. **Request binding** — `provider`, `method`, `dotPath`, and `requestHash` must
|
|
289
|
+
match the actual call, else `PayGateError` (`otp-mismatched-request`).
|
|
290
|
+
7. **Replay check** — a `jti` already in the store throws `PayGateError`
|
|
291
|
+
(`otp-replayed`).
|
|
292
|
+
8. **Consume + dispatch** — the `jti` is recorded, then the HTTP request fires.
|
|
290
293
|
|
|
291
294
|
```ts
|
|
292
|
-
import { PayGateError
|
|
295
|
+
import { PayGateError } from "@apicity/cost";
|
|
293
296
|
|
|
294
297
|
try {
|
|
295
|
-
await provider.post.api.v1.jobs.createTask({ ... }, { otp
|
|
298
|
+
await provider.post.api.v1.jobs.createTask({ ... }, { otp });
|
|
296
299
|
} catch (e) {
|
|
297
300
|
if (e instanceof PayGateError) {
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
301
|
+
// e.code: paygate-not-configured | otp-missing | otp-malformed
|
|
302
|
+
// | otp-invalid-signature | otp-expired
|
|
303
|
+
// | otp-mismatched-request | otp-replayed
|
|
304
|
+
} else throw e;
|
|
303
305
|
}
|
|
304
306
|
```
|
|
305
307
|
|
|
306
308
|
### Failure modes
|
|
307
309
|
|
|
308
|
-
| Condition
|
|
309
|
-
|
|
310
|
-
|
|
|
311
|
-
| Paid endpoint without OTP
|
|
312
|
-
|
|
|
313
|
-
|
|
|
314
|
-
|
|
|
315
|
-
| Mismatched provider/method/dotPath | `
|
|
316
|
-
| Mismatched request hash
|
|
317
|
-
|
|
|
318
|
-
| Unestimable cost | `SpendBoundError` | Unknown model or missing fields |
|
|
310
|
+
| Condition | `PayGateError.code` |
|
|
311
|
+
| ---------------------------------- | ------------------------ |
|
|
312
|
+
| Provider built without a secret | `paygate-not-configured` |
|
|
313
|
+
| Paid endpoint without OTP | `otp-missing` |
|
|
314
|
+
| Malformed envelope | `otp-malformed` |
|
|
315
|
+
| Invalid HMAC signature | `otp-invalid-signature` |
|
|
316
|
+
| Expired OTP (`exp` < now) | `otp-expired` |
|
|
317
|
+
| Mismatched provider/method/dotPath | `otp-mismatched-request` |
|
|
318
|
+
| Mismatched request hash | `otp-mismatched-request` |
|
|
319
|
+
| Replayed OTP (`jti` seen) | `otp-replayed` |
|
|
319
320
|
|
|
320
321
|
### CLI: minting OTPs
|
|
321
322
|
|
|
322
|
-
The `apicity-paygate` binary
|
|
323
|
+
The `apicity-paygate` binary mints OTPs. The secret is read from a **file**
|
|
324
|
+
(never an env var); only the OTP is printed to stdout:
|
|
323
325
|
|
|
324
326
|
```bash
|
|
325
|
-
# Mint an OTP for a specific request
|
|
326
327
|
apicity-paygate otp mint \
|
|
327
|
-
--
|
|
328
|
-
--method POST \
|
|
328
|
+
--secret-file ./paygate.secret \
|
|
329
329
|
--dot-path api.v1.jobs.createTask \
|
|
330
330
|
--payload-file request.json \
|
|
331
|
-
--max-spend 5 \
|
|
332
331
|
--ttl 10m
|
|
333
332
|
```
|
|
334
333
|
|
|
335
|
-
|
|
336
|
-
to stdout on success.
|
|
334
|
+
### Wiring the gate into a provider
|
|
337
335
|
|
|
338
|
-
|
|
336
|
+
Providers apply the gate once at the bottom of their factory using
|
|
337
|
+
`withPaidGate`. The walker descends the HTTP-method roots (`post`, `get`,
|
|
338
|
+
`delete`, `patch`, `put`) and routes every leaf whose `(provider, method,
|
|
339
|
+
dotPath)` is in `PAID_ENDPOINTS` through `dispatchWithPaidGate`. Free leaves
|
|
340
|
+
pass through unchanged; sub-providers, schema records, and other non-route
|
|
341
|
+
properties are returned by reference. The config is passed once and shared
|
|
342
|
+
(one replay store per provider instance):
|
|
339
343
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
344
|
+
```ts
|
|
345
|
+
import { withPaidGate } from "@apicity/cost";
|
|
346
|
+
|
|
347
|
+
export function createKie(opts: KieOptions): KieProvider {
|
|
348
|
+
// ...build endpoint functions...
|
|
349
|
+
return withPaidGate(
|
|
350
|
+
"kie",
|
|
351
|
+
{
|
|
352
|
+
veo: createVeoProvider(...), // sub-provider, untouched
|
|
353
|
+
modelInputSchemas, // data, untouched
|
|
354
|
+
post: { api: { v1: { jobs: { createTask: Object.assign(createTask, { schema }) } } } },
|
|
355
|
+
get: { api: { v1: { jobs: { recordInfo } } } },
|
|
356
|
+
},
|
|
357
|
+
{ config: opts.paygate }
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
```
|
|
343
361
|
|
|
344
|
-
|
|
362
|
+
The gate is generic — `xai` and other providers opt in simply by adding a
|
|
363
|
+
`PAID_ENDPOINTS` entry and threading `{ config: opts.paygate }` through their
|
|
364
|
+
factory.
|
|
345
365
|
|
|
346
|
-
|
|
347
|
-
```bash
|
|
348
|
-
openssl genpkey -algorithm Ed25519 -out paygate-private.pem
|
|
349
|
-
openssl pkey -in paygate-private.pem -pubout -out paygate-public.pem
|
|
350
|
-
```
|
|
351
|
-
2. **Runtime** sets `APICITY_PAYGATE_PUBLIC_KEY_PATH` to the public key.
|
|
352
|
-
3. **Operator** mints OTPs before each paid call using the CLI or a custom
|
|
353
|
-
tool that signs the same payload format.
|
|
354
|
-
4. **Caller** passes `{ otp }` instead of a numeric `maxSpend`:
|
|
355
|
-
```ts
|
|
356
|
-
// Before (deprecated)
|
|
357
|
-
await provider.post.api.v1.jobs.createTask({ ... }, 5);
|
|
366
|
+
### Retry semantics
|
|
358
367
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
368
|
+
The OTP `jti` is consumed **before** `dispatch()` runs. If dispatch later fails
|
|
369
|
+
(network error, upstream 5xx, abort), the `jti` stays consumed and the caller
|
|
370
|
+
must mint a fresh OTP to retry. This is intentional — without it, a hostile
|
|
371
|
+
caller could replay a single OTP on every transient failure. Treat each OTP as
|
|
372
|
+
single-use authority for one network attempt.
|
|
362
373
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
374
|
+
### MCP server
|
|
375
|
+
|
|
376
|
+
The `@apicity/mcp-server` is the code client: start it with
|
|
377
|
+
`--paygate-secret-file <path>` and it holds the secret to **verify** OTPs (it
|
|
378
|
+
never mints). A human mints an OTP out-of-band (same secret) and the caller
|
|
379
|
+
passes it as the paid tool's `otp` argument — so an AI driving the tool cannot
|
|
380
|
+
self-approve.
|
|
366
381
|
|
|
367
382
|
### Minimal operator workflow
|
|
368
383
|
|
|
369
|
-
1. **
|
|
370
|
-
|
|
371
|
-
export APICITY_PAYGATE_PRIVATE_KEY_PATH=./paygate-private.pem
|
|
372
|
-
export APICITY_PAYGATE_PUBLIC_KEY_PATH=./paygate-public.pem
|
|
373
|
-
```
|
|
374
|
-
2. **Prepare a request**:
|
|
375
|
-
```bash
|
|
376
|
-
cat > request.json << 'EOF'
|
|
377
|
-
{
|
|
378
|
-
"model": "kling-3.0/video",
|
|
379
|
-
"input": {
|
|
380
|
-
"prompt": "A cat playing piano",
|
|
381
|
-
"duration": "5",
|
|
382
|
-
"aspect_ratio": "16:9"
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
EOF
|
|
386
|
-
```
|
|
384
|
+
1. **Generate a secret** (one-time) and store it (secret manager / file).
|
|
385
|
+
2. **Prepare a request** JSON file.
|
|
387
386
|
3. **Mint an OTP**:
|
|
388
387
|
```bash
|
|
389
388
|
apicity-paygate otp mint \
|
|
390
|
-
--
|
|
391
|
-
--method POST \
|
|
389
|
+
--secret-file ./paygate.secret \
|
|
392
390
|
--dot-path api.v1.jobs.createTask \
|
|
393
391
|
--payload-file request.json \
|
|
394
|
-
--max-spend 5 \
|
|
395
392
|
--ttl 10m
|
|
396
393
|
```
|
|
397
394
|
4. **Pass the OTP to the caller** (copy-paste, secrets manager, etc.).
|
package/dist/src/cost.d.ts
CHANGED
package/dist/src/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/cost.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,SAAS,CAAC;AAE7D,wBAAgB,
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/cost.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,SAAS,CAAC;AAE7D,wBAAgB,UAAU,IAAI,YAAY,CAIzC"}
|
package/dist/src/cost.js
CHANGED
package/dist/src/cost.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,QAAQ,EAAE,CAAC,GAAoB,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC;KACzD,CAAC;AACJ,CAAC"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createCost } from "./cost";
|
|
2
2
|
export { computeEstimate } from "./compute";
|
|
3
3
|
export { PRICING, PRICING_AS_OF } from "./pricing/index";
|
|
4
4
|
export { MODEL_SLUGS, MODEL_DISPLAY, modelSlug, modelDisplay } from "./slugs";
|
|
@@ -6,8 +6,10 @@ export type { SlugProviderId, SlugModelId } from "./slugs";
|
|
|
6
6
|
export type { CostUnit, ModelPricing, PerUnitPricing, PricedProviderId, RateSource, TokenPricing, } from "./pricing/index";
|
|
7
7
|
export type { CostBreakdown, CostEstimate, CostProvider, CostSource, EstimateRequest, } from "./types";
|
|
8
8
|
export type { ExtractResult, TextExtract } from "./extract/types";
|
|
9
|
-
export { PAID_ENDPOINTS, lookupPaidEndpoint, isPaidEndpoint,
|
|
9
|
+
export { PAID_ENDPOINTS, lookupPaidEndpoint, isPaidEndpoint, } from "./paid-endpoints";
|
|
10
10
|
export type { PaidEndpointKey, PaidEndpointInfo, PaidEndpointEntry, } from "./paid-endpoints";
|
|
11
|
-
export { PayGateError,
|
|
12
|
-
export type { PayGateOtpPayload } from "./paygate";
|
|
11
|
+
export { PayGateError, dispatchWithPaidGate, mintOtp, createReplayStore, canonicalizeJson, canonicalHash, parseOtp, parseTtl, verifyOtp, } from "./paygate";
|
|
12
|
+
export type { PayGateApproval, PayGateConfig, ReplayStore, OtpCall, PayGateOtpPayload, VerifyFailureCode, VerifyOtpInput, VerifyResult, } from "./paygate";
|
|
13
|
+
export { withPaidGate } from "./with-paid-gate";
|
|
14
|
+
export type { WithPaidGateOptions } from "./with-paid-gate";
|
|
13
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9E,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3D,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,eAAe,GAChB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,OAAO,EACP,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createCost } from "./cost.js";
|
|
2
2
|
export { computeEstimate } from "./compute.js";
|
|
3
3
|
export { PRICING, PRICING_AS_OF } from "./pricing/index.js";
|
|
4
4
|
export { MODEL_SLUGS, MODEL_DISPLAY, modelSlug, modelDisplay } from "./slugs.js";
|
|
5
|
-
export { PAID_ENDPOINTS, lookupPaidEndpoint, isPaidEndpoint,
|
|
6
|
-
export { PayGateError, dispatchWithPaidGate, canonicalizeJson, canonicalHash, parseOtp,
|
|
5
|
+
export { PAID_ENDPOINTS, lookupPaidEndpoint, isPaidEndpoint, } from "./paid-endpoints.js";
|
|
6
|
+
export { PayGateError, dispatchWithPaidGate, mintOtp, createReplayStore, canonicalizeJson, canonicalHash, parseOtp, parseTtl, verifyOtp, } from "./paygate.js";
|
|
7
|
+
export { withPaidGate } from "./with-paid-gate.js";
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAsB9E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAO1B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,MAAM,WAAW,CAAC;AAYnB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -43,68 +43,4 @@ export declare function lookupPaidEndpoint(provider: string, method: string, dot
|
|
|
43
43
|
* Unlisted endpoints return `false` (assumed free).
|
|
44
44
|
*/
|
|
45
45
|
export declare function isPaidEndpoint(provider: string, method: string, dotPath: string): boolean;
|
|
46
|
-
/**
|
|
47
|
-
* Error thrown when a paid endpoint is called without an explicit maxSpend.
|
|
48
|
-
*/
|
|
49
|
-
export declare class MaxSpendError extends Error {
|
|
50
|
-
readonly provider: string;
|
|
51
|
-
readonly method: string;
|
|
52
|
-
readonly dotPath: string;
|
|
53
|
-
readonly maxSpend: number;
|
|
54
|
-
constructor(provider: string, method: string, dotPath: string, maxSpend: number);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Error thrown when the estimated cost of a paid endpoint exceeds the
|
|
58
|
-
* caller's maxSpend or when the cost cannot be safely estimated.
|
|
59
|
-
*/
|
|
60
|
-
export declare class SpendBoundError extends Error {
|
|
61
|
-
readonly provider: string;
|
|
62
|
-
readonly method: string;
|
|
63
|
-
readonly dotPath: string;
|
|
64
|
-
readonly maxSpend: number;
|
|
65
|
-
readonly estimatedUsd: number;
|
|
66
|
-
constructor(provider: string, method: string, dotPath: string, maxSpend: number, estimatedUsd: number, message?: string);
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Preflight check for paid endpoints.
|
|
70
|
-
*
|
|
71
|
-
* For paid endpoints, maxSpend defaults to 0 when omitted. maxSpend=0 blocks
|
|
72
|
-
* before the network request with a MaxSpendError. maxSpend>0 authorizes the
|
|
73
|
-
* call to proceed.
|
|
74
|
-
*
|
|
75
|
-
* Free/unlisted endpoints are always allowed regardless of maxSpend.
|
|
76
|
-
*/
|
|
77
|
-
export declare function maxSpendPreflight(provider: string, method: string, dotPath: string, maxSpend?: number): void;
|
|
78
|
-
/**
|
|
79
|
-
* Verify that a cost estimate is within the caller's maxSpend.
|
|
80
|
-
*
|
|
81
|
-
* If the estimate has warnings (could not be computed safely), the spend
|
|
82
|
-
* cannot be bounded and the call is blocked. If the estimated USD exceeds
|
|
83
|
-
* maxSpend, the call is blocked. Otherwise the call proceeds.
|
|
84
|
-
*
|
|
85
|
-
* This must run AFTER maxSpendPreflight, so maxSpend is known to be > 0.
|
|
86
|
-
*/
|
|
87
|
-
export declare function spendBoundCheck(provider: string, method: string, dotPath: string, maxSpend: number | undefined, estimate: {
|
|
88
|
-
usd: number;
|
|
89
|
-
warnings: string[];
|
|
90
|
-
}): void;
|
|
91
|
-
/**
|
|
92
|
-
* Wrap a provider network dispatch with the paid-endpoint guard.
|
|
93
|
-
*
|
|
94
|
-
* This is the canonical boundary enforcement: it runs the preflight check
|
|
95
|
-
* and spend-bound check before the actual HTTP request, and only calls the
|
|
96
|
-
* supplied `dispatch` function when the checks pass.
|
|
97
|
-
*
|
|
98
|
-
* Free/unlisted endpoints return `dispatch()` immediately without guard
|
|
99
|
-
* overhead, so callers that omit `maxSpend` on free endpoints see no change.
|
|
100
|
-
*
|
|
101
|
-
* @param provider - Provider identifier (e.g. "kie", "openai")
|
|
102
|
-
* @param method - HTTP method (e.g. "POST", "GET")
|
|
103
|
-
* @param dotPath - Exact endpoint dot-path (e.g. "api.v1.jobs.createTask")
|
|
104
|
-
* @param payload - Request payload for cost estimation
|
|
105
|
-
* @param maxSpend - Maximum spend authorization in USD (undefined for free endpoints)
|
|
106
|
-
* @param dispatch - The actual network dispatch to wrap
|
|
107
|
-
* @returns The result of `dispatch()`
|
|
108
|
-
*/
|
|
109
|
-
export declare function dispatchWithPaidGuard<T>(provider: string, method: string, dotPath: string, payload: Record<string, unknown>, maxSpend: number | undefined, dispatch: () => Promise<T>): Promise<T>;
|
|
110
46
|
//# sourceMappingURL=paid-endpoints.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paid-endpoints.d.ts","sourceRoot":"","sources":["../../src/paid-endpoints.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paid-endpoints.d.ts","sourceRoot":"","sources":["../../src/paid-endpoints.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,eAAe,CAAC;IACrB,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,iBAAiB,EAetD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,gBAAgB,GAAG,SAAS,CAW9B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAET"}
|