@limitry/sdk 1.0.0-rc.5 → 1.0.0-rc.7
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 +36 -1
- package/README.md +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/product/limits.d.ts +11 -2
- package/dist/product/limits.js +23 -7
- package/dist/resources.gen.d.ts +1 -0
- package/dist/v1.gen.d.ts +5 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,46 @@
|
|
|
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.7 (2026-10-19)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- A refused check's `reason` has a `message`: the refusal in one sentence,
|
|
10
|
+
such as "Refused by AI budget: 3 cents left, resets
|
|
11
|
+
2026-11-01T00:00:00.000Z. Try again in 3600 s." `LimitExceeded` and
|
|
12
|
+
`limitry check` show it as the API writes it, so every client says the
|
|
13
|
+
same. Branch on `allowed` and `reason.code`, never on the message.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- - `held.cost()` refuses a cost the API can't commit (not a whole number
|
|
18
|
+
from 0 to 1,000,000,000): TypeScript throws `RangeError`, Python raises
|
|
19
|
+
`ValueError`, in your code. Before, the commit failed silently after
|
|
20
|
+
the work and its usage was never counted.
|
|
21
|
+
- TypeScript's `held.extend()` throws the API's error, such as for an
|
|
22
|
+
expired hold, as Python's already did. Both send the `ttlSeconds` you
|
|
23
|
+
give as it is, so `0` is refused rather than read as the default.
|
|
24
|
+
- Python checks, commits and releases now retry exactly as TypeScript's
|
|
25
|
+
do: a network error, `408`, `429` or `5xx`, at most twice, all within
|
|
26
|
+
the check's `timeout` (1.5 s) or 5 s for a settle. `standing()` retries
|
|
27
|
+
too, and reports an error answer that isn't JSON.
|
|
28
|
+
- `limitry check` and `limitry sync` refuse `--workspace` with an API key,
|
|
29
|
+
as every other command does, instead of ignoring it.
|
|
30
|
+
|
|
31
|
+
## 1.0.0-rc.6 (2026-10-19)
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- `LimitExceeded` says which limit refused, by name, and when to try
|
|
36
|
+
again: "Refused by AI replies per day: 0 replies left, resets
|
|
37
|
+
2026-10-20T00:00:00.000Z. Try again in 60 s." It used to show only the
|
|
38
|
+
limit's id. `error.limit` (`limit` in Python) is still the id.
|
|
39
|
+
|
|
5
40
|
## 1.0.0-rc.5 (2026-10-16)
|
|
6
41
|
|
|
7
42
|
### Changed
|
|
8
43
|
|
|
9
|
-
- The TypeScript SDK's guide is at `/docs/typescript
|
|
44
|
+
- The TypeScript SDK's guide is at `/docs/typescript/`, beside `/docs/python/` and `/docs/cli/`.
|
|
10
45
|
|
|
11
46
|
## 1.0.0-rc.4 (2026-10-16)
|
|
12
47
|
|
package/README.md
CHANGED
|
@@ -91,9 +91,12 @@ idempotency key, so a retried request happens once.
|
|
|
91
91
|
- [Discord](https://limitry.com/discord)
|
|
92
92
|
- [Report a security issue](https://limitry.com/security/)
|
|
93
93
|
|
|
94
|
-
##
|
|
94
|
+
## Contributing
|
|
95
95
|
|
|
96
96
|
This repository is generated from Limitry's source on each
|
|
97
97
|
release, so pull requests are ported there and credited (see
|
|
98
98
|
[CONTRIBUTING.md](https://github.com/limitry/limitry-typescript/blob/main/CONTRIBUTING.md)).
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
99
102
|
Licensed under the Apache License 2.0.
|
package/dist/index.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ declare function createBaseClient(options: ClientOptions): import("openapi-fetch
|
|
|
79
79
|
reason: {
|
|
80
80
|
code: "limit_exceeded" | "too_many_reservations";
|
|
81
81
|
limit: string | null;
|
|
82
|
+
message: string;
|
|
82
83
|
} | null;
|
|
83
84
|
remaining: components["schemas"]["CheckRemaining"][];
|
|
84
85
|
reservation?: {
|
package/dist/product/limits.d.ts
CHANGED
|
@@ -70,9 +70,18 @@ export type HoldRequest = {
|
|
|
70
70
|
ttlSeconds?: number;
|
|
71
71
|
};
|
|
72
72
|
export type Held = {
|
|
73
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* 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).
|
|
78
|
+
*/
|
|
74
79
|
cost(units: number): void;
|
|
75
|
-
/**
|
|
80
|
+
/**
|
|
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.
|
|
84
|
+
*/
|
|
76
85
|
extend(ttlSeconds?: number): Promise<void>;
|
|
77
86
|
};
|
|
78
87
|
/** Not allowed: a limit is used up — or Limitry is unreachable and a limit fails closed. */
|
package/dist/product/limits.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { apiErrorFrom } from "../errors.js";
|
|
2
|
+
/** The largest cost a commit takes. */
|
|
3
|
+
const MAX_COST = 1_000_000_000;
|
|
4
|
+
function checkedCost(units) {
|
|
5
|
+
if (!Number.isInteger(units) || units < 0 || units > MAX_COST) {
|
|
6
|
+
throw new RangeError(`held.cost(${units}): the cost must be a whole number from 0 to ${MAX_COST}`);
|
|
7
|
+
}
|
|
8
|
+
return units;
|
|
9
|
+
}
|
|
1
10
|
/** Not allowed: a limit is used up — or Limitry is unreachable and a limit fails closed. */
|
|
2
11
|
export class LimitExceeded extends Error {
|
|
3
12
|
reason;
|
|
@@ -9,9 +18,8 @@ export class LimitExceeded extends Error {
|
|
|
9
18
|
const reason = decision?.reason?.code ?? "unavailable";
|
|
10
19
|
super(reason === "unavailable"
|
|
11
20
|
? "Limitry could not be reached and a limit denies when unreachable"
|
|
12
|
-
: reason
|
|
13
|
-
|
|
14
|
-
: `Limit ${decision?.reason?.limit ?? ""} exceeded`.trim());
|
|
21
|
+
: // The API's own sentence (reason.message), one wording everywhere.
|
|
22
|
+
(decision?.reason?.message ?? "Refused"));
|
|
15
23
|
this.name = "LimitExceeded";
|
|
16
24
|
this.reason = reason;
|
|
17
25
|
this.limit = decision?.reason?.limit ?? null;
|
|
@@ -185,7 +193,12 @@ export function createLimits(client, options = {}) {
|
|
|
185
193
|
};
|
|
186
194
|
const idempotencyKey = crypto.randomUUID();
|
|
187
195
|
const decision = await check(body, idempotencyKey);
|
|
188
|
-
const unmetered = {
|
|
196
|
+
const unmetered = {
|
|
197
|
+
// Checked even unmetered: the mistake shows whether or not
|
|
198
|
+
// Limitry answered.
|
|
199
|
+
cost: (units) => void checkedCost(units),
|
|
200
|
+
extend: async () => { },
|
|
201
|
+
};
|
|
189
202
|
if (decision === UNREACHABLE || decision === TIMED_OUT) {
|
|
190
203
|
const unheard = () => decision === TIMED_OUT
|
|
191
204
|
? releaseUnheard(body, idempotencyKey)
|
|
@@ -209,14 +222,17 @@ export function createLimits(client, options = {}) {
|
|
|
209
222
|
let used = estimate;
|
|
210
223
|
const held = {
|
|
211
224
|
cost(units) {
|
|
212
|
-
used = units;
|
|
225
|
+
used = checkedCost(units);
|
|
213
226
|
},
|
|
214
227
|
async extend(ttlSeconds) {
|
|
215
|
-
|
|
228
|
+
// Passed as given: the API refuses a bad one (0, past 3600).
|
|
229
|
+
const { error, response } = await client.POST("/reservations/{reservationId}/extend", {
|
|
216
230
|
params: { path: { reservationId: id } },
|
|
217
|
-
body: ttlSeconds ? {
|
|
231
|
+
body: ttlSeconds === undefined ? {} : { ttlSeconds },
|
|
218
232
|
signal: AbortSignal.timeout(timeoutMs),
|
|
219
233
|
});
|
|
234
|
+
if (error !== undefined)
|
|
235
|
+
throw apiErrorFrom(error, response);
|
|
220
236
|
},
|
|
221
237
|
};
|
|
222
238
|
let result;
|
package/dist/resources.gen.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare function resources(client: RawClient): {
|
|
|
8
8
|
reason: {
|
|
9
9
|
code: "limit_exceeded" | "too_many_reservations";
|
|
10
10
|
limit: string | null;
|
|
11
|
+
message: string;
|
|
11
12
|
} | null;
|
|
12
13
|
remaining: import("./v1.gen.ts").components["schemas"]["CheckRemaining"][];
|
|
13
14
|
reservation?: {
|
package/dist/v1.gen.d.ts
CHANGED
|
@@ -778,6 +778,11 @@ export interface components {
|
|
|
778
778
|
code: "limit_exceeded" | "too_many_reservations";
|
|
779
779
|
/** @example lim_3f0c… */
|
|
780
780
|
limit: string | null;
|
|
781
|
+
/**
|
|
782
|
+
* @description The refusal in one sentence, for people and logs: show it, never parse it (its wording may change). Branch on `allowed` and `code`.
|
|
783
|
+
* @example Refused by AI replies per day: 0 replies left, resets 2026-11-01T00:00:00.000Z. Try again in 3600 s.
|
|
784
|
+
*/
|
|
785
|
+
message: string;
|
|
781
786
|
} | null;
|
|
782
787
|
/** @description Every limit that applied, and what is left in its window. */
|
|
783
788
|
remaining: components["schemas"]["CheckRemaining"][];
|