@limitry/sdk 1.0.0-rc.7 → 1.0.0-rc.8

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/CHANGELOG.md CHANGED
@@ -2,6 +2,78 @@
2
2
 
3
3
  What changed in the Limitry TypeScript SDK (`@limitry/sdk`). Generated from the source on each release; newest first.
4
4
 
5
+ ## 1.0.0-rc.8 (2026-10-21)
6
+
7
+ ### Added
8
+
9
+ - Limits have `counting`: `fast` answers the instant it decides, and
10
+ `guaranteed` stores every count safely before answering, so the limit
11
+ never goes over, even if a server fails. A `total` balance defaults to
12
+ `guaranteed`, every other window to `fast`. Set it when creating or
13
+ updating a limit (`counting`, `--counting`), or in `limitry.json`.
14
+
15
+ ### Changed
16
+
17
+ - - Creating a limit needs only who it is for, the amount and the window:
18
+ `limits.create({ subject: { kind: "user" }, amount: 100, window: "month" })`
19
+ (`limitry limits create --subject '{"kind":"user"}' --amount 100 --window month`).
20
+ `action` defaults to every action (`*`), `unit` to `units`, and `name`
21
+ to the sentence the limit reads as, such as "100 units per user per
22
+ month". If a limit already has that name, the API answers `409`: give
23
+ this one a `name`. `limitry.json` entries still need a `name`.
24
+ - A limit's input names who it is for as `subject: { kind, id }` (was
25
+ `subjectKind` and `subjectId`), the same shape the limit itself has.
26
+ - What a limit counts is fixed once it is created: its subject, action,
27
+ unit, window, `every`, `start` and `rolling`. Changing one answers
28
+ `400 invalid_request`: create a new limit and archive the old one (its
29
+ history stays). Name, amount, fail mode and enabled still change any
30
+ time. `limitry sync` refuses such a change until you rename the entry.
31
+ - A limit says when a check last reached it (`lastCheckedAt`), so you can
32
+ see a limit no check names.
33
+ - One name for each idea, everywhere: the API, both SDKs, the CLI, the MCP
34
+ tools, `limitry.json` and webhooks. Update your code when you upgrade:
35
+
36
+ - `hold()` is `reserve()`: it takes `cost` (was `estimate`), and the block
37
+ gets a `Reservation` (was `Held`; Python `Reservation` and
38
+ `AsyncReservation`), with the same `cost()` and `extend()`.
39
+ - A refusal throws `LimitReached` (was `LimitExceeded`), with `limitId`
40
+ (Python `limit_id`) and `reason` `limit_reached` or
41
+ `too_many_reservations`. When Limitry can't be reached and a limit fails
42
+ closed, you now get a separate `Unavailable` error. "Can't be reached"
43
+ also covers a `402 plan_limit_reached` and a `429` from Limitry's flood
44
+ guard, so each limit's fail mode decides instead of your code getting an
45
+ error.
46
+ - A check's answer lists its limits in `limits` (was `remaining`): read
47
+ `decision.limits[0].remaining`. Every answer that names a limit says
48
+ `limitId`: `reason.limitId`, `limits[].limitId`, `usage.standing`'s
49
+ `limits[].limitId`, and webhook payloads.
50
+ - The refusal code is `limit_reached` (was `limit_exceeded`), and the
51
+ webhook event is `limit.reached` (was `limit.exceeded`): subscribe your
52
+ endpoints to the new name.
53
+ - Usage says `refused` (was `denied`); `usage.subjects` no longer has
54
+ `over` (it is `refused > 0`).
55
+ - Credits: `limits.credits.create()` and `limits.credits.list()` at
56
+ `/v1/limits/{limitId}/credits` (were `limits.grants.*` at `…/grants`),
57
+ ids start `crd_` (were `grt_`), and the approval an agent asks for is
58
+ `limit.credit` (was `limit.grant`).
59
+ - A period that starts on the subject's billing date is
60
+ `start: "billing_date"` (was `"anchor"`), and `subjects.update()` takes
61
+ `billingDate` (was `anchor`); the subject says `billingDate` too.
62
+ - `usage.standing()` and `usage.query()` take one `subject`, written
63
+ `kind:id` (`user:usr_123`), instead of separate kind and id fields
64
+ (`limitry usage standing --subject user:usr_123`).
65
+ - A limit's id starts `lmt_` (was `lim_`); keys still start `lim_test_`
66
+ and `lim_live_`.
67
+ - `limitry sync --preview` (was `--dry-run`), and the API's `preview`
68
+ (was `dryRun`), in what you send and what comes back.
69
+
70
+ ### Removed
71
+
72
+ - Limits no longer have `counting` (Fast or Guaranteed), and the CLI no
73
+ longer has `--counting`: every count is now saved before Limitry answers,
74
+ for every limit. Remove `counting` from your code and from
75
+ `limitry.json`; Limitry ignores it.
76
+
5
77
  ## 1.0.0-rc.7 (2026-10-19)
6
78
 
7
79
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @limitry/sdk
2
2
 
3
- The Limitry TypeScript SDK puts a limit around costly work in one call: `guard` checks before your code runs, and `hold` reserves an estimate, then charges what the work actually cost. Every API operation is a typed method too.
3
+ The Limitry TypeScript SDK puts a limit around costly work in one call: `guard` checks before your code runs, and `reserve` reserves what the work will probably cost, then charges what it actually cost. Every API operation is a typed method too.
4
4
 
5
5
  Limitry is the limits, credits and budgets layer for your software: give each of your users, teams, tenants, API keys or agents an allowance, and before any costly action one call tells your code whether it may happen.
6
6
 
@@ -19,7 +19,7 @@ key (`lim_test_…`) while you build.
19
19
  it counts one AI call against a limit such as 100 a day:
20
20
 
21
21
  ```ts
22
- import { createClient, LimitExceeded } from "@limitry/sdk";
22
+ import { createClient, LimitReached } from "@limitry/sdk";
23
23
 
24
24
  const limitry = createClient(); // reads LIMITRY_API_KEY
25
25
 
@@ -29,7 +29,7 @@ try {
29
29
  () => callModel(prompt),
30
30
  );
31
31
  } catch (error) {
32
- if (error instanceof LimitExceeded) {
32
+ if (error instanceof LimitReached) {
33
33
  console.log(`Try again in ${error.retryAfterSeconds} seconds`);
34
34
  }
35
35
  }
@@ -38,26 +38,28 @@ try {
38
38
  ## Charge what it actually cost
39
39
 
40
40
  When you only know the cost afterwards, such as an AI reply priced by
41
- the token, `hold` reserves an estimate (5 cents here), runs your code
42
- and charges what it used. If your code throws, the hold is released:
41
+ the token, `reserve` reserves what it will probably cost (5 cents here),
42
+ runs your code and charges what it used. If your code throws, the
43
+ reservation is released:
43
44
 
44
45
  ```ts
45
46
  import { createClient } from "@limitry/sdk";
46
47
 
47
48
  const limitry = createClient();
48
49
 
49
- const answer = await limitry.hold(
50
- { subject: { kind: "user", id: "usr_123" }, action: "ai-call", estimate: 5 },
51
- async (held) => {
50
+ const answer = await limitry.reserve(
51
+ { subject: { kind: "user", id: "usr_123" }, action: "ai-call", cost: 5 },
52
+ async (reservation) => {
52
53
  const response = await callModel(prompt);
53
- held.cost(priceCents(response.usage)); // your prices, in cents
54
+ reservation.cost(priceCents(response.usage)); // your prices, in cents
54
55
  return response;
55
56
  },
56
57
  );
57
58
  ```
58
59
 
59
- If Limitry can't be reached, each limit's fail mode decides: `open` lets
60
- the work run, `closed` refuses it.
60
+ A refusal throws `LimitReached`. If Limitry can't be reached, each
61
+ limit's fail mode decides: `open` lets the work run, `closed` throws
62
+ `Unavailable`.
61
63
 
62
64
  ## Everything else
63
65
 
@@ -69,9 +71,9 @@ import { createClient } from "@limitry/sdk";
69
71
 
70
72
  const limitry = createClient();
71
73
 
74
+ // "100 units per user per day for ai-call"
72
75
  await limitry.limits.create({
73
- name: "AI replies per day",
74
- subjectKind: "user",
76
+ subject: { kind: "user" },
75
77
  action: "ai-call",
76
78
  amount: 100,
77
79
  window: "day",
package/dist/index.d.ts CHANGED
@@ -76,12 +76,12 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
76
76
  create: (input: import("./resources.ts").Input<"/checks", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
77
77
  allowed: boolean;
78
78
  id: string;
79
+ limits: components["schemas"]["CheckLimit"][];
79
80
  reason: {
80
- code: "limit_exceeded" | "too_many_reservations";
81
- limit: string | null;
81
+ code: "limit_reached" | "too_many_reservations";
82
+ limitId: string | null;
82
83
  message: string;
83
84
  } | null;
84
- remaining: components["schemas"]["CheckRemaining"][];
85
85
  reservation?: {
86
86
  expiresAt: string;
87
87
  id: string;
@@ -100,15 +100,33 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
100
100
  every: number;
101
101
  failMode: "open" | "closed";
102
102
  id: string;
103
+ lastCheckedAt: string | null;
103
104
  name: string;
104
105
  rolling: boolean;
105
- start: "calendar" | "anchor" | "first_use";
106
+ start: "calendar" | "billing_date" | "first_use";
106
107
  subject: components["schemas"]["LimitSubject"];
107
108
  unit: string;
108
109
  updatedAt: string;
109
110
  version: number;
110
111
  window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
111
112
  }>;
113
+ credits: {
114
+ create: (limitId: string | number, input: import("./resources.ts").Input<"/limits/{limitId}/credits", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
115
+ amount: number;
116
+ createdAt: string;
117
+ createdByUserId: string | null;
118
+ id: string;
119
+ limitId: string;
120
+ note: string;
121
+ subject: {
122
+ id: string;
123
+ kind: string;
124
+ };
125
+ }>;
126
+ list: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
127
+ items: components["schemas"]["Credit"][];
128
+ }>;
129
+ };
112
130
  get: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
113
131
  action: string;
114
132
  amount: number;
@@ -118,32 +136,16 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
118
136
  every: number;
119
137
  failMode: "open" | "closed";
120
138
  id: string;
139
+ lastCheckedAt: string | null;
121
140
  name: string;
122
141
  rolling: boolean;
123
- start: "calendar" | "anchor" | "first_use";
142
+ start: "calendar" | "billing_date" | "first_use";
124
143
  subject: components["schemas"]["LimitSubject"];
125
144
  unit: string;
126
145
  updatedAt: string;
127
146
  version: number;
128
147
  window: "minute" | "hour" | "day" | "week" | "month" | "year" | "total" | "concurrent";
129
148
  }>;
130
- grants: {
131
- create: (limitId: string | number, input: import("./resources.ts").Input<"/limits/{limitId}/grants", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
132
- amount: number;
133
- createdAt: string;
134
- createdByUserId: string | null;
135
- id: string;
136
- limitId: string;
137
- note: string;
138
- subject: {
139
- id: string;
140
- kind: string;
141
- };
142
- }>;
143
- list: (limitId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
144
- items: components["schemas"]["LimitGrant"][];
145
- }>;
146
- };
147
149
  list: (input?: import("./resources.ts").Input<"/limits", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
148
150
  items: components["schemas"]["Limit"][];
149
151
  nextCursor: string | null;
@@ -157,9 +159,10 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
157
159
  every: number;
158
160
  failMode: "open" | "closed";
159
161
  id: string;
162
+ lastCheckedAt: string | null;
160
163
  name: string;
161
164
  rolling: boolean;
162
- start: "calendar" | "anchor" | "first_use";
165
+ start: "calendar" | "billing_date" | "first_use";
163
166
  subject: components["schemas"]["LimitSubject"];
164
167
  unit: string;
165
168
  updatedAt: string;
@@ -169,7 +172,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
169
172
  sync: (input: import("./resources.ts").Input<"/limits/sync", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
170
173
  archived: string[];
171
174
  created: string[];
172
- dryRun: boolean;
175
+ preview: boolean;
173
176
  unchanged: string[];
174
177
  updated: {
175
178
  changes: {
@@ -190,9 +193,10 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
190
193
  every: number;
191
194
  failMode: "open" | "closed";
192
195
  id: string;
196
+ lastCheckedAt: string | null;
193
197
  name: string;
194
198
  rolling: boolean;
195
- start: "calendar" | "anchor" | "first_use";
199
+ start: "calendar" | "billing_date" | "first_use";
196
200
  subject: components["schemas"]["LimitSubject"];
197
201
  unit: string;
198
202
  updatedAt: string;
@@ -225,7 +229,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
225
229
  };
226
230
  subjects: {
227
231
  get: (subjectKind: string | number, subjectId: string | number, options?: import("./resources.ts").RequestOptions) => Promise<{
228
- anchor: string | null;
232
+ billingDate: string | null;
229
233
  subject: components["schemas"]["SubjectRef"];
230
234
  }>;
231
235
  reset: (subjectKind: string | number, subjectId: string | number, input?: import("./resources.ts").Input<"/subjects/{subjectKind}/{subjectId}/reset", "post">, options?: import("./resources.ts").RequestOptions) => Promise<{
@@ -233,7 +237,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
233
237
  subject: components["schemas"]["SubjectRef"];
234
238
  }>;
235
239
  update: (subjectKind: string | number, subjectId: string | number, input: import("./resources.ts").Input<"/subjects/{subjectKind}/{subjectId}", "patch">, options?: import("./resources.ts").RequestOptions) => Promise<{
236
- anchor: string | null;
240
+ billingDate: string | null;
237
241
  subject: components["schemas"]["SubjectRef"];
238
242
  }>;
239
243
  };
@@ -243,7 +247,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
243
247
  limitId: string;
244
248
  points: {
245
249
  allowed: number;
246
- denied: number;
250
+ refused: number;
247
251
  start: string;
248
252
  used: number;
249
253
  }[];
@@ -253,7 +257,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
253
257
  limits: {
254
258
  action: string;
255
259
  amount: number;
256
- limit: string;
260
+ limitId: string;
257
261
  name: string;
258
262
  remaining: number;
259
263
  resetsAt: string | null;
@@ -274,8 +278,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
274
278
  }>;
275
279
  subjects: (input: import("./resources.ts").Input<"/usage/subjects", "get">, options?: import("./resources.ts").RequestOptions) => Promise<{
276
280
  items: {
277
- denied: number;
278
- over: boolean;
281
+ refused: number;
279
282
  remaining: number;
280
283
  subject: {
281
284
  id: string;
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * PRODUCT-OWNED: Limitry's SDK helpers (fork-owned seam — docs/conventions.md
3
3
  * "Fork-owned seams"): re-exported by the SDK entry and published with
4
- * it. `guard` / `hold` (docs/product/roadmap.md slice 6) sit on the client
4
+ * it. `guard` / `reserve` (docs/product/roadmap.md slice 6) sit on the client
5
5
  * (`limitry.guard(…)`, the SDK's `productMethods` seam); `createLimits(client,
6
6
  * options)` gives them with your own timeout or fail mode.
7
7
  */
8
8
  import type { BaseClient } from "../index.ts";
9
- export { createLimits, LimitExceeded, type GuardRequest, type Held, type HoldRequest, type Limits, type LimitsOptions, } from "./limits.ts";
10
- /** Limitry's methods on the client: `limitry.guard(…)`, `limitry.hold(…)`, `limitry.standing(…)`. */
9
+ export { createLimits, LimitReached, Unavailable, type GuardRequest, type Limits, type LimitsOptions, type Reservation, type ReserveRequest, } from "./limits.ts";
10
+ /** Limitry's methods on the client: `limitry.guard(…)`, `limitry.reserve(…)`, `limitry.standing(…)`. */
11
11
  export declare const productMethods: (client: BaseClient) => {
12
12
  guard: <T>(request: import("./limits.ts").GuardRequest, fn: () => Promise<T>) => Promise<T>;
13
- hold: <T>(request: import("./limits.ts").HoldRequest, fn: (held: import("./limits.ts").Held) => Promise<T>) => Promise<T>;
13
+ reserve: <T>(request: import("./limits.ts").ReserveRequest, fn: (reservation: import("./limits.ts").Reservation) => Promise<T>) => Promise<T>;
14
14
  standing: (request: {
15
15
  subject: {
16
16
  kind: string;
@@ -1,7 +1,11 @@
1
1
  import { createLimits } from "./limits.js";
2
- export { createLimits, LimitExceeded, } from "./limits.js";
3
- /** Limitry's methods on the client: `limitry.guard(…)`, `limitry.hold(…)`, `limitry.standing(…)`. */
2
+ export { createLimits, LimitReached, Unavailable, } from "./limits.js";
3
+ /** Limitry's methods on the client: `limitry.guard(…)`, `limitry.reserve(…)`, `limitry.standing(…)`. */
4
4
  export const productMethods = (client) => {
5
5
  const limits = createLimits(client);
6
- return { guard: limits.guard, hold: limits.hold, standing: limits.standing };
6
+ return {
7
+ guard: limits.guard,
8
+ reserve: limits.reserve,
9
+ standing: limits.standing,
10
+ };
7
11
  };
@@ -13,33 +13,34 @@ import type { BaseClient, Schemas } from "../index.ts";
13
13
  * );
14
14
  *
15
15
  * // Cost known afterwards (an AI reply's cents), or "at most N at
16
- * // once": hold an estimate, do the work, commit what it used —
17
- * // released on failure.
18
- * const answer = await limitry.hold(
19
- * { subject: { kind: "user", id: user.id }, action: "ai-call", estimate: 5 },
20
- * async (held) => {
16
+ * // once": reserve what it will probably cost, do the work, commit
17
+ * // what it used — released on failure.
18
+ * const answer = await limitry.reserve(
19
+ * { subject: { kind: "user", id: user.id }, action: "ai-call", cost: 5 },
20
+ * async (reservation) => {
21
21
  * const res = await callModel(prompt);
22
- * held.cost(priceCents(res.usage));
22
+ * reservation.cost(priceCents(res.usage));
23
23
  * return res;
24
24
  * },
25
25
  * );
26
26
  *
27
- * A refusal throws `LimitExceeded` (with `retryAfterSeconds`). When
28
- * Limitry cannot be reached (an error, a 5xx, or no answer within
29
- * `timeoutMs`) — or the workspace is past its plan's allowance (402
30
- * `plan_limit_reached`) — each limit's fail mode decides: the last decision's
31
- * `failMode` for this subject and action is remembered in memory, and
32
- * `closed` refuses (`LimitExceeded` with reason `unavailable`) while
33
- * `open` — the default, and the answer before any decision was seen —
34
- * lets the work run unmetered.
27
+ * A refusal throws `LimitReached` (with `limitId` and
28
+ * `retryAfterSeconds`). When Limitry cannot be reached — an error, a 5xx,
29
+ * no answer within `timeoutMs`, the workspace past its plan's allowance
30
+ * (402 `plan_limit_reached`) or the edge's flood guard (429) — each
31
+ * limit's fail mode decides: the last decision's `failMode` for this
32
+ * subject and action is remembered in memory, and `closed` throws
33
+ * `Unavailable` while `open` — the default, and the answer before any
34
+ * decision was seen — lets the work run unmetered.
35
35
  *
36
- * Retries are safe (docs/product idempotency): each guard or hold sends
37
- * one Idempotency-Key, which the client's own retries reuse, so a check
38
- * counts once however often it is sent. A hold whose check timed out may
39
- * have been granted all the same: once the work is done, `hold` sends the
40
- * check again with the same key — a replay, nothing counted twice — and
41
- * releases the hold it finds, rather than leave it taken until it expires.
42
- * Commits and releases retry too (settling twice answers the same).
36
+ * Retries are safe (docs/product idempotency): each guard or reserve
37
+ * sends one Idempotency-Key, which the client's own retries reuse, so a
38
+ * check counts once however often it is sent. A reservation whose check
39
+ * timed out may have been made all the same: once the work is done,
40
+ * `reserve` sends the check again with the same key — a replay, nothing
41
+ * counted twice — and releases the reservation it finds, rather than
42
+ * leave it taken until it expires. Commits and releases retry too
43
+ * (committing or releasing twice answers the same).
43
44
  */
44
45
  type Decision = Schemas["CheckDecision"];
45
46
  type Subject = {
@@ -60,38 +61,47 @@ export type GuardRequest = {
60
61
  /** Pools it also draws from (a team's, an org's). */
61
62
  shared?: Subject[];
62
63
  };
63
- export type HoldRequest = {
64
+ export type ReserveRequest = {
64
65
  subject: Subject;
65
66
  action: string;
66
- /** What it will probably use — held until you commit the actual cost. Default 1. */
67
- estimate?: number;
67
+ /** What it will probably use — reserved until you commit the actual cost. Default 1. */
68
+ cost?: number;
68
69
  shared?: Subject[];
69
- /** How long the hold lasts if never settled (default 300, at most 3600). */
70
+ /** How long the reservation lasts if never committed or released (default 300, at most 3600). */
70
71
  ttlSeconds?: number;
71
72
  };
72
- export type Held = {
73
+ export type Reservation = {
73
74
  /**
74
75
  * The cost actually used — committed when the work returns. Default: the
75
- * estimate. A whole number from 0 to 1,000,000,000, as the API commits:
76
- * anything else throws a RangeError here, in your code, rather than a
77
- * commit the API refuses after the work (whose usage would go uncounted).
76
+ * reserved cost. A whole number from 0 to 1,000,000,000, as the API
77
+ * commits: anything else throws a RangeError here, in your code, rather
78
+ * than a commit the API refuses after the work (whose usage would go
79
+ * uncounted).
78
80
  */
79
81
  cost(units: number): void;
80
82
  /**
81
- * Keep the hold for longer work: it expires `ttlSeconds` from now
82
- * (default 300, 1 to 3600). Throws the API's error, such as for a hold
83
- * that already expired.
83
+ * Keep the reservation for longer work: it expires `ttlSeconds` from now
84
+ * (default 300, 1 to 3600). Throws the API's error, such as for a
85
+ * reservation that already expired.
84
86
  */
85
87
  extend(ttlSeconds?: number): Promise<void>;
86
88
  };
87
- /** Not allowed: a limit is used up — or Limitry is unreachable and a limit fails closed. */
88
- export declare class LimitExceeded extends Error {
89
- readonly reason: "limit_exceeded" | "too_many_reservations" | "unavailable";
90
- /** The limit that refused; null when unavailable or too many holds. */
91
- readonly limit: string | null;
89
+ /** Refused: a limit is reached, or the subject holds too many open reservations. */
90
+ export declare class LimitReached extends Error {
91
+ readonly reason: "limit_reached" | "too_many_reservations";
92
+ /** The limit that refused; null for too many open reservations. */
93
+ readonly limitId: string | null;
92
94
  readonly retryAfterSeconds: number | null;
93
- readonly decision: Decision | null;
94
- constructor(decision: Decision | null);
95
+ readonly decision: Decision;
96
+ constructor(decision: Decision);
97
+ }
98
+ /**
99
+ * Limitry could not be reached (an error, a 5xx, a timeout, the plan's
100
+ * allowance used up, or the flood guard's 429) and a limit on this
101
+ * subject and action fails closed. With `open`, the work runs instead.
102
+ */
103
+ export declare class Unavailable extends Error {
104
+ constructor();
95
105
  }
96
106
  export declare function createLimits(client: BaseClient, options?: LimitsOptions): {
97
107
  /**
@@ -108,12 +118,12 @@ export declare function createLimits(client: BaseClient, options?: LimitsOptions
108
118
  /** Checks `cost`, runs `fn` only if allowed, and returns its result. */
109
119
  guard<T>(request: GuardRequest, fn: () => Promise<T>): Promise<T>;
110
120
  /**
111
- * Holds `estimate`, runs `fn`, then commits the cost it reported
112
- * (`held.cost(n)`, default the estimate) — or releases the hold if
113
- * `fn` throws, and rethrows. A concurrent limit's slot is held for
114
- * exactly as long as `fn` runs.
121
+ * Reserves `cost`, runs `fn`, then commits the cost it reported
122
+ * (`reservation.cost(n)`, default the reserved cost) — or releases the
123
+ * reservation if `fn` throws, and rethrows. A concurrent limit's slot
124
+ * is taken for exactly as long as `fn` runs.
115
125
  */
116
- hold<T>(request: HoldRequest, fn: (held: Held) => Promise<T>): Promise<T>;
126
+ reserve<T>(request: ReserveRequest, fn: (reservation: Reservation) => Promise<T>): Promise<T>;
117
127
  };
118
128
  export type Limits = ReturnType<typeof createLimits>;
119
129
  export {};