llm-retry-kit 0.1.0 → 0.2.1
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 +295 -51
- package/dist/backoff.d.ts +2 -1
- package/dist/backoff.d.ts.map +1 -1
- package/dist/backoff.js +35 -6
- package/dist/backoff.js.map +1 -1
- package/dist/budget.d.ts +2 -1
- package/dist/budget.d.ts.map +1 -1
- package/dist/budget.js +5 -2
- package/dist/budget.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/retry.d.ts +9 -1
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +257 -55
- package/dist/retry.js.map +1 -1
- package/dist/types.d.ts +48 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -1,14 +1,52 @@
|
|
|
1
1
|
# llm-retry-kit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/llm-retry-kit)
|
|
4
|
+
[](https://www.npmjs.com/package/llm-retry-kit)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](./package.json)
|
|
7
|
+
[](./tsconfig.json)
|
|
8
|
+
[](https://github.com/JavadRostami3/llm-retry-kit/actions)
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
Small resilience layer for production LLM calls. `llm-retry-kit` gives you
|
|
11
|
+
provider-aware retries, fallback chains, jittered exponential backoff,
|
|
12
|
+
`Retry-After` handling, budget tracking, cancellation, timeouts, and
|
|
13
|
+
observability hooks without runtime dependencies.
|
|
7
14
|
|
|
8
15
|
```bash
|
|
9
16
|
npm install llm-retry-kit
|
|
10
17
|
```
|
|
11
18
|
|
|
19
|
+
## Why llm-retry-kit?
|
|
20
|
+
|
|
21
|
+
LLM APIs fail in ways that normal API wrappers often do not model well:
|
|
22
|
+
|
|
23
|
+
- `429` rate limits need backoff, not immediate loops.
|
|
24
|
+
- `500`, `503`, `504`, and Anthropic `529 overloaded_error` are usually
|
|
25
|
+
transient and often worth retrying or failing over.
|
|
26
|
+
- `400`, `401`, `403`, and request-too-large errors are usually request or
|
|
27
|
+
credential problems and should not blindly retry or fallback.
|
|
28
|
+
- Failed retry attempts can still count toward provider rate limits.
|
|
29
|
+
- Production apps need cancellation, budget limits, and logs around every
|
|
30
|
+
attempt.
|
|
31
|
+
|
|
32
|
+
This package keeps the core primitive small: you provide the actual SDK call,
|
|
33
|
+
and `llm-retry-kit` manages the reliability policy around it.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- Retry transient LLM failures with exponential backoff and jitter.
|
|
38
|
+
- Respect `Retry-After` headers from provider errors.
|
|
39
|
+
- Chain named providers or models with explicit fallback behavior.
|
|
40
|
+
- Avoid fallback on non-transient client errors by default.
|
|
41
|
+
- Customize retry and fallback decisions with `shouldRetry` and
|
|
42
|
+
`shouldFallback`.
|
|
43
|
+
- Track token usage and estimated cost.
|
|
44
|
+
- Use custom input/output token pricing through `costCalculator`.
|
|
45
|
+
- Abort long calls and retry sleeps with `AbortSignal` or `timeoutMs`.
|
|
46
|
+
- Observe attempts, retries, success, failure, and budget events.
|
|
47
|
+
- Strict TypeScript types.
|
|
48
|
+
- ESM package with no runtime dependencies.
|
|
49
|
+
|
|
12
50
|
## Quick Start
|
|
13
51
|
|
|
14
52
|
```ts
|
|
@@ -18,11 +56,14 @@ import OpenAI from 'openai'
|
|
|
18
56
|
const openai = new OpenAI()
|
|
19
57
|
|
|
20
58
|
const result = await llmRetry({
|
|
21
|
-
fn: async () => {
|
|
22
|
-
const response = await openai.chat.completions.create(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
59
|
+
fn: async ({ signal }) => {
|
|
60
|
+
const response = await openai.chat.completions.create(
|
|
61
|
+
{
|
|
62
|
+
model: 'gpt-4o-mini',
|
|
63
|
+
messages: [{ role: 'user', content: 'Hello!' }],
|
|
64
|
+
},
|
|
65
|
+
{ signal }
|
|
66
|
+
)
|
|
26
67
|
|
|
27
68
|
return {
|
|
28
69
|
data: response.choices[0]?.message.content ?? '',
|
|
@@ -35,37 +76,143 @@ const result = await llmRetry({
|
|
|
35
76
|
: undefined,
|
|
36
77
|
}
|
|
37
78
|
},
|
|
79
|
+
maxRetries: 3,
|
|
80
|
+
initialDelayMs: 1000,
|
|
81
|
+
maxDelayMs: 30000,
|
|
38
82
|
})
|
|
39
83
|
|
|
40
84
|
console.log(result.data)
|
|
85
|
+
console.log(result.provider)
|
|
41
86
|
console.log(result.attempts)
|
|
42
87
|
console.log(result.totalCostUSD)
|
|
43
88
|
```
|
|
44
89
|
|
|
45
|
-
## Fallback Example
|
|
90
|
+
## Complete Provider Fallback Example
|
|
91
|
+
|
|
92
|
+
This example tries OpenAI first, then falls back to Anthropic only for transient
|
|
93
|
+
failures. Client errors like invalid requests or bad credentials stop the chain
|
|
94
|
+
by default.
|
|
46
95
|
|
|
47
96
|
```ts
|
|
97
|
+
import Anthropic from '@anthropic-ai/sdk'
|
|
98
|
+
import OpenAI from 'openai'
|
|
48
99
|
import { llmRetry } from 'llm-retry-kit'
|
|
49
100
|
|
|
101
|
+
const openai = new OpenAI()
|
|
102
|
+
const anthropic = new Anthropic()
|
|
103
|
+
|
|
104
|
+
const prompt = 'Summarize the following support ticket...'
|
|
105
|
+
|
|
106
|
+
const result = await llmRetry({
|
|
107
|
+
providers: [
|
|
108
|
+
{
|
|
109
|
+
name: 'openai:gpt-4o-mini',
|
|
110
|
+
maxRetries: 2,
|
|
111
|
+
fn: async ({ signal }) => {
|
|
112
|
+
const response = await openai.chat.completions.create(
|
|
113
|
+
{
|
|
114
|
+
model: 'gpt-4o-mini',
|
|
115
|
+
messages: [{ role: 'user', content: prompt }],
|
|
116
|
+
},
|
|
117
|
+
{ signal }
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
data: response.choices[0]?.message.content ?? '',
|
|
122
|
+
usage: response.usage
|
|
123
|
+
? {
|
|
124
|
+
promptTokens: response.usage.prompt_tokens,
|
|
125
|
+
completionTokens: response.usage.completion_tokens,
|
|
126
|
+
totalTokens: response.usage.total_tokens,
|
|
127
|
+
}
|
|
128
|
+
: undefined,
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'anthropic:claude-sonnet',
|
|
134
|
+
maxRetries: 1,
|
|
135
|
+
fn: async ({ signal }) => {
|
|
136
|
+
const response = await anthropic.messages.create(
|
|
137
|
+
{
|
|
138
|
+
model: 'claude-sonnet-4-6',
|
|
139
|
+
max_tokens: 1024,
|
|
140
|
+
messages: [{ role: 'user', content: prompt }],
|
|
141
|
+
},
|
|
142
|
+
{ signal }
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
const text = response.content
|
|
146
|
+
.filter((block) => block.type === 'text')
|
|
147
|
+
.map((block) => block.text)
|
|
148
|
+
.join('')
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
data: text,
|
|
152
|
+
usage: {
|
|
153
|
+
promptTokens: response.usage.input_tokens,
|
|
154
|
+
completionTokens: response.usage.output_tokens,
|
|
155
|
+
totalTokens: response.usage.input_tokens + response.usage.output_tokens,
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
timeoutMs: 45_000,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
console.log({
|
|
165
|
+
provider: result.provider,
|
|
166
|
+
usedFallback: result.usedFallback,
|
|
167
|
+
attempts: result.attempts,
|
|
168
|
+
answer: result.data,
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Simple Fallback API
|
|
173
|
+
|
|
174
|
+
For smaller apps, `fn` plus `fallback` is still supported.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
50
177
|
const result = await llmRetry({
|
|
51
178
|
fn: async () => callPrimaryModel(),
|
|
52
179
|
fallback: async () => callFallbackModel(),
|
|
53
|
-
maxRetries:
|
|
54
|
-
initialDelayMs: 1000,
|
|
55
|
-
maxDelayMs: 30000,
|
|
180
|
+
maxRetries: 2,
|
|
56
181
|
})
|
|
182
|
+
```
|
|
57
183
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
184
|
+
## Configuration
|
|
185
|
+
|
|
186
|
+
### Retry Timing
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
await llmRetry({
|
|
190
|
+
fn: myLLMCall,
|
|
191
|
+
maxRetries: 4,
|
|
192
|
+
initialDelayMs: 500,
|
|
193
|
+
maxDelayMs: 60_000,
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Retries use exponential backoff with jitter. If the provider exposes a
|
|
198
|
+
`Retry-After` header, that delay is preferred.
|
|
199
|
+
|
|
200
|
+
### Timeout And Cancellation
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const controller = new AbortController()
|
|
204
|
+
|
|
205
|
+
const result = await llmRetry({
|
|
206
|
+
fn: async ({ signal }) => myLLMCall({ signal }),
|
|
207
|
+
signal: controller.signal,
|
|
208
|
+
timeoutMs: 30_000,
|
|
209
|
+
})
|
|
61
210
|
```
|
|
62
211
|
|
|
63
|
-
|
|
212
|
+
`timeoutMs` aborts the wrapper and retry sleeps. Passing `signal` into your SDK
|
|
213
|
+
call also lets the underlying request stop when the SDK supports it.
|
|
64
214
|
|
|
65
|
-
|
|
66
|
-
function. It cannot know the exact cost of a future LLM call before that call
|
|
67
|
-
finishes, so the budget guard is best used to stop later retries or fallback
|
|
68
|
-
calls after tracked usage reaches the configured cap.
|
|
215
|
+
### Budget Tracking
|
|
69
216
|
|
|
70
217
|
```ts
|
|
71
218
|
const result = await llmRetry({
|
|
@@ -78,47 +225,119 @@ const result = await llmRetry({
|
|
|
78
225
|
})
|
|
79
226
|
```
|
|
80
227
|
|
|
81
|
-
|
|
228
|
+
For real provider pricing, prefer `costCalculator`:
|
|
82
229
|
|
|
83
230
|
```ts
|
|
84
231
|
const result = await llmRetry({
|
|
85
232
|
fn: myLLMCall,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
233
|
+
costCalculator: (usage) => {
|
|
234
|
+
const inputCost = usage.promptTokens * 0.00000015
|
|
235
|
+
const outputCost = usage.completionTokens * 0.0000006
|
|
236
|
+
return inputCost + outputCost
|
|
237
|
+
},
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Budget tracking is based on the `usage` object returned by your function. A
|
|
242
|
+
wrapper cannot know the final cost of an in-flight LLM call before the provider
|
|
243
|
+
returns usage, so `maxCostUSD` is a guard for later attempts and fallback calls.
|
|
244
|
+
|
|
245
|
+
### Custom Retry Policy
|
|
246
|
+
|
|
247
|
+
Use `context.defaultShouldRetry` to compose with the built-in transient error
|
|
248
|
+
detection.
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
await llmRetry({
|
|
252
|
+
fn: myLLMCall,
|
|
253
|
+
shouldRetry: (error, context) => {
|
|
254
|
+
if (error.message.includes('insufficient quota')) return false
|
|
255
|
+
return context.defaultShouldRetry
|
|
256
|
+
},
|
|
257
|
+
})
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
By default, `llm-retry-kit` retries common transient failures such as HTTP
|
|
261
|
+
`408`, `409`, `429`, `5xx`, Anthropic `529`, timeout, network, and overload
|
|
262
|
+
errors.
|
|
263
|
+
|
|
264
|
+
### Custom Fallback Policy
|
|
265
|
+
|
|
266
|
+
Fallback is a separate decision from retry. By default, fallback is allowed only
|
|
267
|
+
after transient failures. If you intentionally want to fallback for a known
|
|
268
|
+
client-side case, opt in explicitly.
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
await llmRetry({
|
|
272
|
+
providers: [
|
|
273
|
+
{ name: 'small-context-model', fn: callSmallModel },
|
|
274
|
+
{ name: 'large-context-model', fn: callLargeModel },
|
|
275
|
+
],
|
|
276
|
+
shouldFallback: (error, context) => {
|
|
277
|
+
if (error.message.includes('context length')) {
|
|
278
|
+
return context.nextProvider === 'large-context-model'
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return context.defaultShouldFallback
|
|
92
282
|
},
|
|
93
283
|
})
|
|
94
284
|
```
|
|
95
285
|
|
|
96
|
-
|
|
286
|
+
### Observability
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
await llmRetry({
|
|
290
|
+
fn: myLLMCall,
|
|
291
|
+
onAttempt: (context) => {
|
|
292
|
+
console.log(`Calling ${context.provider}, attempt ${context.attempt}`)
|
|
293
|
+
},
|
|
294
|
+
onRetry: (attempt, error, delayMs, context) => {
|
|
295
|
+
console.log(`${context.provider} failed: ${error.message}`)
|
|
296
|
+
console.log(`Retrying in ${delayMs}ms`)
|
|
297
|
+
},
|
|
298
|
+
onSuccess: (context) => {
|
|
299
|
+
console.log(`Cost so far: $${context.totalCostUSD}`)
|
|
300
|
+
},
|
|
301
|
+
onFailure: (error) => {
|
|
302
|
+
console.error(error)
|
|
303
|
+
},
|
|
304
|
+
})
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## API Reference
|
|
97
308
|
|
|
98
309
|
### `llmRetry(options)`
|
|
99
310
|
|
|
100
311
|
| Option | Type | Default | Description |
|
|
101
312
|
| --- | --- | --- | --- |
|
|
102
|
-
| `fn` | `() => Promise<LLMResponse<T>>` |
|
|
103
|
-
| `fallback` | `() => Promise<LLMResponse<T>>` | optional | Backup
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
313
|
+
| `fn` | `(context) => Promise<LLMResponse<T>>` | optional | Primary LLM call for the simple API. |
|
|
314
|
+
| `fallback` | `(context) => Promise<LLMResponse<T>>` | optional | Backup LLM call for the simple API. |
|
|
315
|
+
| `providers` | `RetryProvider<T>[]` | optional | Explicit provider/model chain. |
|
|
316
|
+
| `maxRetries` | `number` | `3` | Retries after the first attempt. |
|
|
317
|
+
| `maxCostUSD` | `number` | optional | Maximum tracked cost before later attempts stop. |
|
|
318
|
+
| `costPer1kTokens` | `number` | `0.002` | Simple cost estimate. |
|
|
319
|
+
| `costCalculator` | `(usage, context) => number` | optional | Custom cost calculation. |
|
|
107
320
|
| `initialDelayMs` | `number` | `1000` | Initial retry delay. |
|
|
108
321
|
| `maxDelayMs` | `number` | `30000` | Maximum retry delay. |
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
322
|
+
| `timeoutMs` | `number` | optional | Abort wrapper after this time. |
|
|
323
|
+
| `signal` | `AbortSignal` | optional | External cancellation signal. |
|
|
324
|
+
| `shouldRetry` | `(error, context) => boolean \| Promise<boolean>` | optional | Override retry decisions. |
|
|
325
|
+
| `shouldFallback` | `(error, context) => boolean \| Promise<boolean>` | optional | Override provider fallback decisions. |
|
|
326
|
+
| `onAttempt` | `(context) => void` | optional | Called before each attempt. |
|
|
327
|
+
| `onRetry` | `(attempt, error, delayMs, context) => void` | optional | Called before retry wait. |
|
|
328
|
+
| `onSuccess` | `(context) => void` | optional | Called after a successful response. |
|
|
329
|
+
| `onFailure` | `(error) => void` | optional | Called before final failure is thrown. |
|
|
330
|
+
| `onBudgetExceeded` | `(spentUSD, limitUSD) => void` | optional | Called when budget is exhausted. |
|
|
111
331
|
|
|
112
|
-
### `
|
|
332
|
+
### `RetryProvider<T>`
|
|
113
333
|
|
|
114
334
|
```ts
|
|
115
335
|
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
336
|
+
name: string
|
|
337
|
+
fn: (context: RetryAttemptContext) => Promise<LLMResponse<T>>
|
|
338
|
+
maxRetries?: number
|
|
339
|
+
costPer1kTokens?: number
|
|
340
|
+
costCalculator?: (usage, context) => number
|
|
122
341
|
}
|
|
123
342
|
```
|
|
124
343
|
|
|
@@ -128,24 +347,49 @@ const result = await llmRetry({
|
|
|
128
347
|
{
|
|
129
348
|
data: T
|
|
130
349
|
attempts: number
|
|
350
|
+
provider: string
|
|
131
351
|
usedFallback: boolean
|
|
132
352
|
totalCostUSD: number
|
|
133
353
|
totalTokens: number
|
|
134
354
|
}
|
|
135
355
|
```
|
|
136
356
|
|
|
137
|
-
|
|
357
|
+
### `LLMRetryError`
|
|
138
358
|
|
|
139
|
-
|
|
359
|
+
```ts
|
|
360
|
+
{
|
|
361
|
+
name: 'LLMRetryError'
|
|
362
|
+
primaryError: Error | null
|
|
363
|
+
fallbackError: Error | null
|
|
364
|
+
totalCostUSD: number
|
|
365
|
+
totalTokens: number
|
|
366
|
+
attempts: number
|
|
367
|
+
providers: string[]
|
|
368
|
+
reason: 'failure' | 'budget_exceeded' | 'aborted'
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Defaults
|
|
373
|
+
|
|
374
|
+
| Setting | Default |
|
|
375
|
+
| --- | --- |
|
|
376
|
+
| `maxRetries` | `3` |
|
|
377
|
+
| `initialDelayMs` | `1000` |
|
|
378
|
+
| `maxDelayMs` | `30000` |
|
|
379
|
+
| `costPer1kTokens` | `0.002` |
|
|
380
|
+
| fallback on client errors | `false` |
|
|
381
|
+
| fallback on transient errors | `true` |
|
|
382
|
+
| runtime dependencies | none |
|
|
140
383
|
|
|
141
|
-
|
|
142
|
-
- HTTP `5xx`
|
|
143
|
-
- timeout errors
|
|
144
|
-
- network connection errors
|
|
145
|
-
- overloaded server errors
|
|
384
|
+
## Development
|
|
146
385
|
|
|
147
|
-
|
|
148
|
-
|
|
386
|
+
```bash
|
|
387
|
+
npm install
|
|
388
|
+
npm run typecheck
|
|
389
|
+
npm test
|
|
390
|
+
npm run build
|
|
391
|
+
npm pack --dry-run
|
|
392
|
+
```
|
|
149
393
|
|
|
150
394
|
## License
|
|
151
395
|
|
package/dist/backoff.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare function calculateBackoff(attempt: number, initialDelayMs: number, maxDelayMs: number): number;
|
|
2
|
-
export declare function sleep(ms: number): Promise<void>;
|
|
2
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
3
3
|
export declare function isRetryableError(error: unknown): boolean;
|
|
4
4
|
export declare function extractRetryAfter(error: unknown): number | null;
|
|
5
|
+
export declare function createAbortError(): Error;
|
|
5
6
|
//# sourceMappingURL=backoff.d.ts.map
|
package/dist/backoff.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backoff.d.ts","sourceRoot":"","sources":["../src/backoff.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,GACjB,MAAM,CAMR;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"backoff.d.ts","sourceRoot":"","sources":["../src/backoff.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,GACjB,MAAM,CAMR;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA2DxD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAkC/D;AAED,wBAAgB,gBAAgB,IAAI,KAAK,CAIxC"}
|
package/dist/backoff.js
CHANGED
|
@@ -4,15 +4,27 @@ export function calculateBackoff(attempt, initialDelayMs, maxDelayMs) {
|
|
|
4
4
|
const delay = exponential + jitter;
|
|
5
5
|
return Math.min(Math.max(delay, initialDelayMs), maxDelayMs);
|
|
6
6
|
}
|
|
7
|
-
export function sleep(ms) {
|
|
8
|
-
|
|
7
|
+
export function sleep(ms, signal) {
|
|
8
|
+
if (signal?.aborted) {
|
|
9
|
+
return Promise.reject(createAbortError());
|
|
10
|
+
}
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const timeout = setTimeout(resolve, ms);
|
|
13
|
+
signal?.addEventListener('abort', () => {
|
|
14
|
+
clearTimeout(timeout);
|
|
15
|
+
reject(createAbortError());
|
|
16
|
+
}, { once: true });
|
|
17
|
+
});
|
|
9
18
|
}
|
|
10
19
|
export function isRetryableError(error) {
|
|
11
20
|
if (!(error instanceof Error))
|
|
12
21
|
return false;
|
|
13
22
|
const err = error;
|
|
14
23
|
const status = toNumber(err.status ?? err.statusCode);
|
|
15
|
-
if (status ===
|
|
24
|
+
if (status === 408 ||
|
|
25
|
+
status === 409 ||
|
|
26
|
+
status === 429 ||
|
|
27
|
+
(status !== null && status >= 500 && status <= 599)) {
|
|
16
28
|
return true;
|
|
17
29
|
}
|
|
18
30
|
const code = typeof err.code === 'string' ? err.code.toLowerCase() : '';
|
|
@@ -23,6 +35,8 @@ export function isRetryableError(error) {
|
|
|
23
35
|
'enotfound',
|
|
24
36
|
'eai_again',
|
|
25
37
|
'rate_limit_exceeded',
|
|
38
|
+
'conflict',
|
|
39
|
+
'overloaded_error',
|
|
26
40
|
].includes(code)) {
|
|
27
41
|
return true;
|
|
28
42
|
}
|
|
@@ -32,6 +46,8 @@ export function isRetryableError(error) {
|
|
|
32
46
|
'rate_limit',
|
|
33
47
|
'too many requests',
|
|
34
48
|
'429',
|
|
49
|
+
'408',
|
|
50
|
+
'409',
|
|
35
51
|
'server error',
|
|
36
52
|
'500',
|
|
37
53
|
'502',
|
|
@@ -44,6 +60,7 @@ export function isRetryableError(error) {
|
|
|
44
60
|
'network',
|
|
45
61
|
'socket',
|
|
46
62
|
'overloaded',
|
|
63
|
+
'overloaded_error',
|
|
47
64
|
];
|
|
48
65
|
return retryablePatterns.some((pattern) => message.includes(pattern));
|
|
49
66
|
}
|
|
@@ -55,20 +72,32 @@ export function extractRetryAfter(error) {
|
|
|
55
72
|
if (retryAfter !== null) {
|
|
56
73
|
return retryAfter * 1000;
|
|
57
74
|
}
|
|
58
|
-
const
|
|
75
|
+
const response = err['response'];
|
|
76
|
+
const headerValue = getHeader(err['headers'], 'retry-after') ??
|
|
77
|
+
getHeader(response?.['headers'], 'retry-after');
|
|
59
78
|
if (!headerValue) {
|
|
60
79
|
return null;
|
|
61
80
|
}
|
|
62
|
-
const
|
|
81
|
+
const trimmedHeaderValue = headerValue.trim();
|
|
82
|
+
const isNumericDelay = /^\d+(\.\d+)?$/.test(trimmedHeaderValue);
|
|
83
|
+
const seconds = Number(trimmedHeaderValue);
|
|
63
84
|
if (Number.isFinite(seconds)) {
|
|
64
85
|
return seconds * 1000;
|
|
65
86
|
}
|
|
66
|
-
|
|
87
|
+
if (isNumericDelay) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const dateMs = Date.parse(trimmedHeaderValue);
|
|
67
91
|
if (Number.isFinite(dateMs)) {
|
|
68
92
|
return Math.max(dateMs - Date.now(), 0);
|
|
69
93
|
}
|
|
70
94
|
return null;
|
|
71
95
|
}
|
|
96
|
+
export function createAbortError() {
|
|
97
|
+
const error = new Error('The operation was aborted');
|
|
98
|
+
error.name = 'AbortError';
|
|
99
|
+
return error;
|
|
100
|
+
}
|
|
72
101
|
function toNumber(value) {
|
|
73
102
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
74
103
|
return value;
|
package/dist/backoff.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backoff.js","sourceRoot":"","sources":["../src/backoff.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,cAAsB,EACtB,UAAkB;IAElB,MAAM,WAAW,GAAG,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;IACzD,MAAM,MAAM,GAAG,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAC3D,MAAM,KAAK,GAAG,WAAW,GAAG,MAAM,CAAA;IAElC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,EAAE,UAAU,CAAC,CAAA;AAC9D,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EAAU;
|
|
1
|
+
{"version":3,"file":"backoff.js","sourceRoot":"","sources":["../src/backoff.ts"],"names":[],"mappings":"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"}
|
package/dist/budget.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ export declare class BudgetTracker {
|
|
|
5
5
|
private readonly costPer1kTokens;
|
|
6
6
|
private readonly maxCostUSD;
|
|
7
7
|
constructor(costPer1kTokens: number, maxCostUSD?: number);
|
|
8
|
-
add(usage: TokenUsage): void;
|
|
8
|
+
add(usage: TokenUsage, costUSD?: number): void;
|
|
9
|
+
estimate(usage: TokenUsage): number;
|
|
9
10
|
isExceeded(): boolean;
|
|
10
11
|
get spent(): number;
|
|
11
12
|
get tokens(): number;
|
package/dist/budget.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,qBAAa,aAAa;IACxB,OAAO,CAAC,WAAW,CAAI;IACvB,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;gBAE9B,eAAe,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAaxD,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,qBAAa,aAAa;IACxB,OAAO,CAAC,WAAW,CAAI;IACvB,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;gBAE9B,eAAe,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAaxD,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAK9C,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM;IAInC,UAAU,IAAI,OAAO;IAKrB,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAED,OAAO,IAAI,MAAM;CAKlB"}
|
package/dist/budget.js
CHANGED
|
@@ -13,9 +13,12 @@ export class BudgetTracker {
|
|
|
13
13
|
this.costPer1kTokens = costPer1kTokens;
|
|
14
14
|
this.maxCostUSD = maxCostUSD ?? null;
|
|
15
15
|
}
|
|
16
|
-
add(usage) {
|
|
16
|
+
add(usage, costUSD) {
|
|
17
17
|
this.totalTokens += usage.totalTokens;
|
|
18
|
-
this.totalCostUSD +=
|
|
18
|
+
this.totalCostUSD += costUSD ?? this.estimate(usage);
|
|
19
|
+
}
|
|
20
|
+
estimate(usage) {
|
|
21
|
+
return (usage.totalTokens / 1000) * this.costPer1kTokens;
|
|
19
22
|
}
|
|
20
23
|
isExceeded() {
|
|
21
24
|
if (this.maxCostUSD === null)
|
package/dist/budget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAChB,WAAW,GAAG,CAAC,CAAA;IACf,YAAY,GAAG,CAAC,CAAA;IACP,eAAe,CAAQ;IACvB,UAAU,CAAe;IAE1C,YAAY,eAAuB,EAAE,UAAmB;QACtD,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QACvE,CAAC;QAED,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAClE,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,IAAI,CAAA;IACtC,CAAC;IAED,GAAG,CAAC,KAAiB;
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAChB,WAAW,GAAG,CAAC,CAAA;IACf,YAAY,GAAG,CAAC,CAAA;IACP,eAAe,CAAQ;IACvB,UAAU,CAAe;IAE1C,YAAY,eAAuB,EAAE,UAAmB;QACtD,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QACvE,CAAC;QAED,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAClE,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,eAAe,CAAA;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,IAAI,CAAA;IACtC,CAAC;IAED,GAAG,CAAC,KAAiB,EAAE,OAAgB;QACrC,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAA;QACrC,IAAI,CAAC,YAAY,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACtD,CAAC;IAED,QAAQ,CAAC,KAAiB;QACxB,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe,CAAA;IAC1D,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE,OAAO,KAAK,CAAA;QAC1C,OAAO,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,UAAU,CAAA;IAC7C,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,OAAO;QACL,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACrE,OAAO,IAAI,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,UAAU,CAAA;IACzE,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { llmRetry, LLMRetryError } from './retry.js';
|
|
1
|
+
export { BudgetExceededError, llmRetry, LLMRetryError } from './retry.js';
|
|
2
2
|
export { BudgetTracker } from './budget.js';
|
|
3
|
-
export { calculateBackoff, isRetryableError } from './backoff.js';
|
|
4
|
-
export type {
|
|
3
|
+
export { calculateBackoff, extractRetryAfter, isRetryableError } from './backoff.js';
|
|
4
|
+
export type { CostCalculator, FallbackDecisionContext, LLMCall, LLMResponse, RetryAttemptContext, RetryDecisionContext, RetryOptions, RetryProvider, RetryResult, RetrySuccessContext, RetryableError, ShouldFallback, ShouldRetry, TokenUsage, } from './types.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpF,YAAY,EACV,cAAc,EACd,uBAAuB,EACvB,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { llmRetry, LLMRetryError } from './retry.js';
|
|
1
|
+
export { BudgetExceededError, llmRetry, LLMRetryError } from './retry.js';
|
|
2
2
|
export { BudgetTracker } from './budget.js';
|
|
3
|
-
export { calculateBackoff, isRetryableError } from './backoff.js';
|
|
3
|
+
export { calculateBackoff, extractRetryAfter, isRetryableError } from './backoff.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/retry.d.ts
CHANGED
|
@@ -5,6 +5,14 @@ export declare class LLMRetryError extends Error {
|
|
|
5
5
|
readonly fallbackError: Error | null;
|
|
6
6
|
readonly totalCostUSD: number;
|
|
7
7
|
readonly totalTokens: number;
|
|
8
|
-
|
|
8
|
+
readonly attempts: number;
|
|
9
|
+
readonly providers: string[];
|
|
10
|
+
readonly reason: 'failure' | 'budget_exceeded' | 'aborted';
|
|
11
|
+
constructor(message: string, primaryError: Error | null, fallbackError: Error | null, totalCostUSD: number, totalTokens: number, attempts?: number, providers?: string[], reason?: 'failure' | 'budget_exceeded' | 'aborted');
|
|
12
|
+
}
|
|
13
|
+
export declare class BudgetExceededError extends Error {
|
|
14
|
+
readonly spentUSD: number;
|
|
15
|
+
readonly limitUSD: number | null;
|
|
16
|
+
constructor(spentUSD: number, limitUSD: number | null);
|
|
9
17
|
}
|
|
10
18
|
//# sourceMappingURL=retry.d.ts.map
|
package/dist/retry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAMV,YAAY,EAEZ,WAAW,EAGZ,MAAM,YAAY,CAAA;AAEnB,wBAAsB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAyKnF;AAyMD,qBAAa,aAAc,SAAQ,KAAK;aAGpB,YAAY,EAAE,KAAK,GAAG,IAAI;aAC1B,aAAa,EAAE,KAAK,GAAG,IAAI;aAC3B,YAAY,EAAE,MAAM;aACpB,WAAW,EAAE,MAAM;aACnB,QAAQ;aACR,SAAS,EAAE,MAAM,EAAE;aACnB,MAAM,EAAE,SAAS,GAAG,iBAAiB,GAAG,SAAS;gBAPjE,OAAO,EAAE,MAAM,EACC,YAAY,EAAE,KAAK,GAAG,IAAI,EAC1B,aAAa,EAAE,KAAK,GAAG,IAAI,EAC3B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,QAAQ,SAAI,EACZ,SAAS,GAAE,MAAM,EAAO,EACxB,MAAM,GAAE,SAAS,GAAG,iBAAiB,GAAG,SAAqB;CAKhF;AAED,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,QAAQ,EAAE,MAAM;aAChB,QAAQ,EAAE,MAAM,GAAG,IAAI;gBADvB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,IAAI;CAM1C"}
|
package/dist/retry.js
CHANGED
|
@@ -1,70 +1,243 @@
|
|
|
1
|
-
import { calculateBackoff, extractRetryAfter, isRetryableError, sleep } from './backoff.js';
|
|
1
|
+
import { calculateBackoff, createAbortError, extractRetryAfter, isRetryableError, sleep, } from './backoff.js';
|
|
2
2
|
import { BudgetTracker } from './budget.js';
|
|
3
3
|
export async function llmRetry(options) {
|
|
4
|
-
const {
|
|
5
|
-
validateOptions({ maxRetries, initialDelayMs, maxDelayMs });
|
|
4
|
+
const { maxRetries = 3, maxCostUSD, costPer1kTokens = 0.002, initialDelayMs = 1000, maxDelayMs = 30000, timeoutMs, signal, shouldRetry, shouldFallback, onAttempt, onRetry, onSuccess, onFailure, onBudgetExceeded, } = options;
|
|
5
|
+
validateOptions({ maxRetries, initialDelayMs, maxDelayMs, timeoutMs });
|
|
6
|
+
const providers = normalizeProviders(options, maxRetries);
|
|
7
|
+
const startedAt = Date.now();
|
|
6
8
|
const budget = new BudgetTracker(costPer1kTokens, maxCostUSD);
|
|
7
|
-
|
|
9
|
+
const runtimeSignal = createRuntimeSignal(signal, timeoutMs);
|
|
8
10
|
let attempts = 0;
|
|
11
|
+
let lastError = null;
|
|
12
|
+
let primaryError = null;
|
|
13
|
+
let fallbackError = null;
|
|
9
14
|
let budgetExceededNotified = false;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
budget.
|
|
15
|
+
try {
|
|
16
|
+
for (let providerIndex = 0; providerIndex < providers.length; providerIndex++) {
|
|
17
|
+
const provider = providers[providerIndex];
|
|
18
|
+
const providerMaxRetries = provider.maxRetries ?? maxRetries;
|
|
19
|
+
let providerShouldFallback = false;
|
|
20
|
+
for (let retryAttempt = 0; retryAttempt <= providerMaxRetries; retryAttempt++) {
|
|
21
|
+
if (runtimeSignal.signal?.aborted) {
|
|
22
|
+
throw createAbortError();
|
|
23
|
+
}
|
|
24
|
+
if (budget.isExceeded()) {
|
|
25
|
+
budgetExceededNotified = notifyBudgetExceeded(budget.spent, budget.limit, onBudgetExceeded, budgetExceededNotified);
|
|
26
|
+
throw new BudgetExceededError(budget.spent, budget.limit);
|
|
27
|
+
}
|
|
28
|
+
attempts += 1;
|
|
29
|
+
const context = createAttemptContext({
|
|
30
|
+
attempt: attempts,
|
|
31
|
+
retryAttempt,
|
|
32
|
+
provider,
|
|
33
|
+
providerIndex,
|
|
34
|
+
startedAt,
|
|
35
|
+
signal: runtimeSignal.signal,
|
|
36
|
+
lastError,
|
|
37
|
+
});
|
|
38
|
+
onAttempt?.(context);
|
|
39
|
+
try {
|
|
40
|
+
const response = await runWithAbort(provider.fn(context), runtimeSignal.signal);
|
|
41
|
+
const costUSD = trackUsage({
|
|
42
|
+
response,
|
|
43
|
+
context,
|
|
44
|
+
provider,
|
|
45
|
+
defaultCostPer1kTokens: costPer1kTokens,
|
|
46
|
+
defaultCostCalculator: options.costCalculator,
|
|
47
|
+
budget,
|
|
48
|
+
});
|
|
49
|
+
onSuccess?.({
|
|
50
|
+
...context,
|
|
51
|
+
costUSD,
|
|
52
|
+
totalCostUSD: budget.spent,
|
|
53
|
+
totalTokens: budget.tokens,
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
data: response.data,
|
|
57
|
+
attempts,
|
|
58
|
+
provider: provider.name,
|
|
59
|
+
usedFallback: providerIndex > 0,
|
|
60
|
+
totalCostUSD: budget.spent,
|
|
61
|
+
totalTokens: budget.tokens,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
66
|
+
lastError = err;
|
|
67
|
+
if (providerIndex === 0) {
|
|
68
|
+
primaryError = err;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
fallbackError = err;
|
|
72
|
+
}
|
|
73
|
+
const decisionContext = {
|
|
74
|
+
...context,
|
|
75
|
+
maxRetries: providerMaxRetries,
|
|
76
|
+
defaultShouldRetry: isRetryableError(err),
|
|
77
|
+
};
|
|
78
|
+
const retry = await shouldRetryAttempt({
|
|
79
|
+
error: err,
|
|
80
|
+
context: decisionContext,
|
|
81
|
+
shouldRetry,
|
|
82
|
+
retryAttempt,
|
|
83
|
+
maxRetries: providerMaxRetries,
|
|
84
|
+
});
|
|
85
|
+
if (!retry) {
|
|
86
|
+
providerShouldFallback = await shouldFallbackFromProvider({
|
|
87
|
+
error: err,
|
|
88
|
+
context,
|
|
89
|
+
nextProvider: providers[providerIndex + 1],
|
|
90
|
+
nextProviderIndex: providerIndex + 1,
|
|
91
|
+
shouldFallback,
|
|
92
|
+
});
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
const serverDelay = extractRetryAfter(err);
|
|
96
|
+
const delay = serverDelay ?? calculateBackoff(retryAttempt, initialDelayMs, maxDelayMs);
|
|
97
|
+
onRetry?.(attempts, err, delay, decisionContext);
|
|
98
|
+
await sleep(delay, runtimeSignal.signal);
|
|
99
|
+
}
|
|
20
100
|
}
|
|
21
|
-
|
|
22
|
-
data: response.data,
|
|
23
|
-
attempts,
|
|
24
|
-
usedFallback: false,
|
|
25
|
-
totalCostUSD: budget.spent,
|
|
26
|
-
totalTokens: budget.tokens,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
31
|
-
lastError = err;
|
|
32
|
-
const isLastAttempt = retryIndex === maxRetries;
|
|
33
|
-
if (isLastAttempt || !isRetryableError(err)) {
|
|
101
|
+
if (providerIndex < providers.length - 1 && !providerShouldFallback) {
|
|
34
102
|
break;
|
|
35
103
|
}
|
|
36
|
-
const serverDelay = extractRetryAfter(error);
|
|
37
|
-
const delay = serverDelay ?? calculateBackoff(retryIndex, initialDelayMs, maxDelayMs);
|
|
38
|
-
onRetry?.(attempts, err, delay);
|
|
39
|
-
await sleep(delay);
|
|
40
104
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
attempts += 1;
|
|
44
|
-
try {
|
|
45
|
-
const response = await fallback();
|
|
46
|
-
if (response.usage) {
|
|
47
|
-
budget.add(response.usage);
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
data: response.data,
|
|
51
|
-
attempts,
|
|
52
|
-
usedFallback: true,
|
|
53
|
-
totalCostUSD: budget.spent,
|
|
54
|
-
totalTokens: budget.tokens,
|
|
55
|
-
};
|
|
105
|
+
if (budget.isExceeded()) {
|
|
106
|
+
budgetExceededNotified = notifyBudgetExceeded(budget.spent, budget.limit, onBudgetExceeded, budgetExceededNotified);
|
|
56
107
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
108
|
+
throw new Error(lastError?.message ?? 'No provider returned a successful response');
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
112
|
+
const reason = getFailureReason(err);
|
|
113
|
+
const retryError = new LLMRetryError(`LLM call failed after ${attempts} attempt${attempts === 1 ? '' : 's'}: ${err.message}`, primaryError ?? lastError, fallbackError, budget.spent, budget.tokens, attempts, providers.map((provider) => provider.name), reason);
|
|
114
|
+
onFailure?.(retryError);
|
|
115
|
+
throw retryError;
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
runtimeSignal.cleanup();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function normalizeProviders(options, defaultMaxRetries) {
|
|
122
|
+
if (options.providers && options.providers.length > 0) {
|
|
123
|
+
if (options.fn || options.fallback) {
|
|
124
|
+
throw new Error('Use either providers or fn/fallback, not both');
|
|
62
125
|
}
|
|
126
|
+
return options.providers.map((provider) => ({
|
|
127
|
+
...provider,
|
|
128
|
+
maxRetries: provider.maxRetries ?? defaultMaxRetries,
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
if (!options.fn) {
|
|
132
|
+
throw new Error('llmRetry requires fn or at least one provider');
|
|
63
133
|
}
|
|
64
|
-
|
|
65
|
-
|
|
134
|
+
const providers = [
|
|
135
|
+
{
|
|
136
|
+
name: 'primary',
|
|
137
|
+
fn: options.fn,
|
|
138
|
+
maxRetries: defaultMaxRetries,
|
|
139
|
+
costCalculator: options.costCalculator,
|
|
140
|
+
costPer1kTokens: options.costPer1kTokens,
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
if (options.fallback) {
|
|
144
|
+
providers.push({
|
|
145
|
+
name: 'fallback',
|
|
146
|
+
fn: options.fallback,
|
|
147
|
+
maxRetries: 0,
|
|
148
|
+
costCalculator: options.costCalculator,
|
|
149
|
+
costPer1kTokens: options.costPer1kTokens,
|
|
150
|
+
});
|
|
66
151
|
}
|
|
67
|
-
|
|
152
|
+
return providers;
|
|
153
|
+
}
|
|
154
|
+
function createAttemptContext(options) {
|
|
155
|
+
return {
|
|
156
|
+
attempt: options.attempt,
|
|
157
|
+
retryAttempt: options.retryAttempt,
|
|
158
|
+
provider: options.provider.name,
|
|
159
|
+
providerIndex: options.providerIndex,
|
|
160
|
+
elapsedMs: Date.now() - options.startedAt,
|
|
161
|
+
signal: options.signal,
|
|
162
|
+
lastError: options.lastError ?? undefined,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async function shouldRetryAttempt(options) {
|
|
166
|
+
if (options.error.name === 'AbortError') {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (options.retryAttempt >= options.maxRetries) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (options.shouldRetry) {
|
|
173
|
+
return options.shouldRetry(options.error, options.context);
|
|
174
|
+
}
|
|
175
|
+
return isRetryableError(options.error);
|
|
176
|
+
}
|
|
177
|
+
async function shouldFallbackFromProvider(options) {
|
|
178
|
+
if (!options.nextProvider) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const fallbackContext = {
|
|
182
|
+
...options.context,
|
|
183
|
+
defaultShouldFallback: isRetryableError(options.error),
|
|
184
|
+
nextProvider: options.nextProvider.name,
|
|
185
|
+
nextProviderIndex: options.nextProviderIndex,
|
|
186
|
+
};
|
|
187
|
+
if (options.shouldFallback) {
|
|
188
|
+
return options.shouldFallback(options.error, fallbackContext);
|
|
189
|
+
}
|
|
190
|
+
return fallbackContext.defaultShouldFallback;
|
|
191
|
+
}
|
|
192
|
+
function trackUsage(options) {
|
|
193
|
+
const usage = options.response.usage;
|
|
194
|
+
if (!usage) {
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
const calculator = options.provider.costCalculator ?? options.defaultCostCalculator;
|
|
198
|
+
const costUSD = calculator
|
|
199
|
+
? calculator(usage, options.context)
|
|
200
|
+
: calculateDefaultCost(usage, options.provider.costPer1kTokens ?? options.defaultCostPer1kTokens);
|
|
201
|
+
options.budget.add(usage, costUSD);
|
|
202
|
+
return costUSD;
|
|
203
|
+
}
|
|
204
|
+
function calculateDefaultCost(usage, costPer1kTokens) {
|
|
205
|
+
return (usage.totalTokens / 1000) * costPer1kTokens;
|
|
206
|
+
}
|
|
207
|
+
function runWithAbort(promise, signal) {
|
|
208
|
+
if (!signal) {
|
|
209
|
+
return promise;
|
|
210
|
+
}
|
|
211
|
+
if (signal.aborted) {
|
|
212
|
+
return Promise.reject(createAbortError());
|
|
213
|
+
}
|
|
214
|
+
return new Promise((resolve, reject) => {
|
|
215
|
+
const abort = () => reject(createAbortError());
|
|
216
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
217
|
+
promise.then((value) => {
|
|
218
|
+
signal.removeEventListener('abort', abort);
|
|
219
|
+
resolve(value);
|
|
220
|
+
}, (error) => {
|
|
221
|
+
signal.removeEventListener('abort', abort);
|
|
222
|
+
reject(error);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function createRuntimeSignal(signal, timeoutMs) {
|
|
227
|
+
if (timeoutMs === undefined) {
|
|
228
|
+
return { signal, cleanup: () => undefined };
|
|
229
|
+
}
|
|
230
|
+
const controller = new AbortController();
|
|
231
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
232
|
+
const abortFromParent = () => controller.abort();
|
|
233
|
+
signal?.addEventListener('abort', abortFromParent, { once: true });
|
|
234
|
+
return {
|
|
235
|
+
signal: controller.signal,
|
|
236
|
+
cleanup: () => {
|
|
237
|
+
clearTimeout(timeout);
|
|
238
|
+
signal?.removeEventListener('abort', abortFromParent);
|
|
239
|
+
},
|
|
240
|
+
};
|
|
68
241
|
}
|
|
69
242
|
function notifyBudgetExceeded(spentUSD, limitUSD, callback, alreadyNotified) {
|
|
70
243
|
if (!alreadyNotified && limitUSD !== null) {
|
|
@@ -77,15 +250,41 @@ export class LLMRetryError extends Error {
|
|
|
77
250
|
fallbackError;
|
|
78
251
|
totalCostUSD;
|
|
79
252
|
totalTokens;
|
|
80
|
-
|
|
253
|
+
attempts;
|
|
254
|
+
providers;
|
|
255
|
+
reason;
|
|
256
|
+
constructor(message, primaryError, fallbackError, totalCostUSD, totalTokens, attempts = 0, providers = [], reason = 'failure') {
|
|
81
257
|
super(message);
|
|
82
258
|
this.primaryError = primaryError;
|
|
83
259
|
this.fallbackError = fallbackError;
|
|
84
260
|
this.totalCostUSD = totalCostUSD;
|
|
85
261
|
this.totalTokens = totalTokens;
|
|
262
|
+
this.attempts = attempts;
|
|
263
|
+
this.providers = providers;
|
|
264
|
+
this.reason = reason;
|
|
86
265
|
this.name = 'LLMRetryError';
|
|
87
266
|
}
|
|
88
267
|
}
|
|
268
|
+
export class BudgetExceededError extends Error {
|
|
269
|
+
spentUSD;
|
|
270
|
+
limitUSD;
|
|
271
|
+
constructor(spentUSD, limitUSD) {
|
|
272
|
+
const limit = limitUSD === null ? 'unknown' : `$${limitUSD}`;
|
|
273
|
+
super(`Budget exceeded: $${spentUSD.toFixed(6)} / ${limit}`);
|
|
274
|
+
this.spentUSD = spentUSD;
|
|
275
|
+
this.limitUSD = limitUSD;
|
|
276
|
+
this.name = 'BudgetExceededError';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function getFailureReason(error) {
|
|
280
|
+
if (error instanceof BudgetExceededError) {
|
|
281
|
+
return 'budget_exceeded';
|
|
282
|
+
}
|
|
283
|
+
if (error.name === 'AbortError') {
|
|
284
|
+
return 'aborted';
|
|
285
|
+
}
|
|
286
|
+
return 'failure';
|
|
287
|
+
}
|
|
89
288
|
function validateOptions(options) {
|
|
90
289
|
if (!Number.isInteger(options.maxRetries) || options.maxRetries < 0) {
|
|
91
290
|
throw new Error('maxRetries must be a non-negative integer');
|
|
@@ -99,5 +298,8 @@ function validateOptions(options) {
|
|
|
99
298
|
if (options.maxDelayMs < options.initialDelayMs) {
|
|
100
299
|
throw new Error('maxDelayMs must be greater than or equal to initialDelayMs');
|
|
101
300
|
}
|
|
301
|
+
if (options.timeoutMs !== undefined && options.timeoutMs < 0) {
|
|
302
|
+
throw new Error('timeoutMs must be greater than or equal to 0');
|
|
303
|
+
}
|
|
102
304
|
}
|
|
103
305
|
//# sourceMappingURL=retry.js.map
|
package/dist/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,OAAwB;IACxD,MAAM,EACJ,EAAE,EACF,QAAQ,EACR,UAAU,GAAG,CAAC,EACd,UAAU,EACV,eAAe,GAAG,KAAK,EACvB,cAAc,GAAG,IAAI,EACrB,UAAU,GAAG,KAAK,EAClB,OAAO,EACP,gBAAgB,GACjB,GAAG,OAAO,CAAA;IAEX,eAAe,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAA;IAE3D,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,eAAe,EAAE,UAAU,CAAC,CAAA;IAC7D,IAAI,SAAS,GAAiB,IAAI,CAAA;IAClC,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,IAAI,sBAAsB,GAAG,KAAK,CAAA;IAElC,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,IAAI,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC;QAChE,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;YACxB,sBAAsB,GAAG,oBAAoB,CAC3C,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,KAAK,EACZ,gBAAgB,EAChB,sBAAsB,CACvB,CAAA;YACD,MAAK;QACP,CAAC;QAED,QAAQ,IAAI,CAAC,CAAA;QAEb,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,EAAE,EAAE,CAAA;YAE3B,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC5B,CAAC;YAED,OAAO;gBACL,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,QAAQ;gBACR,YAAY,EAAE,KAAK;gBACnB,YAAY,EAAE,MAAM,CAAC,KAAK;gBAC1B,WAAW,EAAE,MAAM,CAAC,MAAM;aAC3B,CAAA;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACrE,SAAS,GAAG,GAAG,CAAA;YAEf,MAAM,aAAa,GAAG,UAAU,KAAK,UAAU,CAAA;YAC/C,IAAI,aAAa,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5C,MAAK;YACP,CAAC;YAED,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;YAC5C,MAAM,KAAK,GAAG,WAAW,IAAI,gBAAgB,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,CAAC,CAAA;YAErF,OAAO,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;YAC/B,MAAM,KAAK,CAAC,KAAK,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;QACrC,QAAQ,IAAI,CAAC,CAAA;QAEb,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,EAAE,CAAA;YAEjC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC5B,CAAC;YAED,OAAO;gBACL,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,QAAQ;gBACR,YAAY,EAAE,IAAI;gBAClB,YAAY,EAAE,MAAM,CAAC,KAAK;gBAC1B,WAAW,EAAE,MAAM,CAAC,MAAM;aAC3B,CAAA;QACH,CAAC;QAAC,OAAO,aAAa,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,aAAa,YAAY,KAAK;gBACxC,CAAC,CAAC,aAAa;gBACf,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAA;YAEpC,MAAM,IAAI,aAAa,CACrB,8CAA8C,SAAS,EAAE,OAAO,IAAI,eAAe,eAAe,GAAG,CAAC,OAAO,EAAE,EAC/G,SAAS,EACT,GAAG,EACH,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,MAAM,CACd,CAAA;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;QACxB,oBAAoB,CAClB,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,KAAK,EACZ,gBAAgB,EAChB,sBAAsB,CACvB,CAAA;IACH,CAAC;IAED,MAAM,IAAI,aAAa,CACrB,yBAAyB,QAAQ,WAAW,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE,OAAO,IAAI,iBAAiB,EAAE,EACnH,SAAS,EACT,IAAI,EACJ,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,MAAM,CACd,CAAA;AACH,CAAC;AAED,SAAS,oBAAoB,CAC3B,QAAgB,EAChB,QAAuB,EACvB,QAA0C,EAC1C,eAAwB;IAExB,IAAI,CAAC,eAAe,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC1C,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAChC,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IAGpB;IACA;IACA;IACA;IALlB,YACE,OAAe,EACC,YAA0B,EAC1B,aAA2B,EAC3B,YAAoB,EACpB,WAAmB;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAA;QALE,iBAAY,GAAZ,YAAY,CAAc;QAC1B,kBAAa,GAAb,aAAa,CAAc;QAC3B,iBAAY,GAAZ,YAAY,CAAQ;QACpB,gBAAW,GAAX,WAAW,CAAQ;QAGnC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC7B,CAAC;CACF;AAED,SAAS,eAAe,CAAC,OAIxB;IACC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IAED,IAAI,OAAO,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;IAED,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IAED,IAAI,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAA;IAC/E,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -7,23 +7,67 @@ export interface LLMResponse<T = unknown> {
|
|
|
7
7
|
data: T;
|
|
8
8
|
usage?: TokenUsage;
|
|
9
9
|
}
|
|
10
|
+
export interface RetryAttemptContext {
|
|
11
|
+
attempt: number;
|
|
12
|
+
retryAttempt: number;
|
|
13
|
+
provider: string;
|
|
14
|
+
providerIndex: number;
|
|
15
|
+
elapsedMs: number;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
lastError?: Error;
|
|
18
|
+
}
|
|
19
|
+
export interface RetryDecisionContext extends RetryAttemptContext {
|
|
20
|
+
maxRetries: number;
|
|
21
|
+
defaultShouldRetry: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface FallbackDecisionContext extends RetryAttemptContext {
|
|
24
|
+
defaultShouldFallback: boolean;
|
|
25
|
+
nextProvider?: string;
|
|
26
|
+
nextProviderIndex?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface RetrySuccessContext extends RetryAttemptContext {
|
|
29
|
+
costUSD: number;
|
|
30
|
+
totalCostUSD: number;
|
|
31
|
+
totalTokens: number;
|
|
32
|
+
}
|
|
33
|
+
export type LLMCall<T = unknown> = (context: RetryAttemptContext) => Promise<LLMResponse<T>>;
|
|
34
|
+
export type CostCalculator = (usage: TokenUsage, context: RetryAttemptContext) => number;
|
|
35
|
+
export type ShouldRetry = (error: Error, context: RetryDecisionContext) => boolean | Promise<boolean>;
|
|
36
|
+
export type ShouldFallback = (error: Error, context: FallbackDecisionContext) => boolean | Promise<boolean>;
|
|
37
|
+
export interface RetryProvider<T = unknown> {
|
|
38
|
+
name: string;
|
|
39
|
+
fn: LLMCall<T>;
|
|
40
|
+
maxRetries?: number;
|
|
41
|
+
costPer1kTokens?: number;
|
|
42
|
+
costCalculator?: CostCalculator;
|
|
43
|
+
}
|
|
10
44
|
export interface RetryOptions<T = unknown> {
|
|
11
|
-
fn
|
|
12
|
-
fallback?:
|
|
45
|
+
fn?: LLMCall<T>;
|
|
46
|
+
fallback?: LLMCall<T>;
|
|
47
|
+
providers?: Array<RetryProvider<T>>;
|
|
13
48
|
maxRetries?: number;
|
|
14
49
|
maxCostUSD?: number;
|
|
15
50
|
costPer1kTokens?: number;
|
|
51
|
+
costCalculator?: CostCalculator;
|
|
16
52
|
initialDelayMs?: number;
|
|
17
53
|
maxDelayMs?: number;
|
|
18
|
-
|
|
54
|
+
timeoutMs?: number;
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
shouldRetry?: ShouldRetry;
|
|
57
|
+
shouldFallback?: ShouldFallback;
|
|
58
|
+
onAttempt?: (context: RetryAttemptContext) => void;
|
|
59
|
+
onRetry?: (attempt: number, error: Error, delayMs: number, context: RetryDecisionContext) => void;
|
|
60
|
+
onSuccess?: (context: RetrySuccessContext) => void;
|
|
61
|
+
onFailure?: (error: Error) => void;
|
|
19
62
|
onBudgetExceeded?: (spentUSD: number, limitUSD: number) => void;
|
|
20
63
|
}
|
|
21
64
|
export interface RetryResult<T = unknown> {
|
|
22
65
|
data: T;
|
|
23
66
|
attempts: number;
|
|
67
|
+
provider: string;
|
|
24
68
|
usedFallback: boolean;
|
|
25
69
|
totalCostUSD: number;
|
|
26
70
|
totalTokens: number;
|
|
27
71
|
}
|
|
28
|
-
export type RetryableError = 'rate_limit' | 'server_error' | 'timeout' | 'network_error';
|
|
72
|
+
export type RetryableError = 'rate_limit' | 'server_error' | 'timeout' | 'network_error' | 'conflict' | 'overloaded';
|
|
29
73
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,KAAK,CAAA;CAClB;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE,qBAAqB,EAAE,OAAO,CAAA;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,OAAO,IAAI,CACjC,OAAO,EAAE,mBAAmB,KACzB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAE5B,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,KAAK,MAAM,CAAA;AAExF,MAAM,MAAM,WAAW,GAAG,CACxB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,oBAAoB,KAC1B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/B,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,uBAAuB,KAC7B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/B,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACnC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAClD,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,KAC1B,IAAI,CAAA;IACT,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAClD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAClC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAChE;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,CAAC,CAAA;IACP,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,cAAc,GACd,SAAS,GACT,eAAe,GACf,UAAU,GACV,YAAY,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-retry-kit",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Resilience toolkit for LLM APIs with retries, provider fallback, budget tracking, aborts, and observability.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -42,8 +42,16 @@
|
|
|
42
42
|
"gpt",
|
|
43
43
|
"claude"
|
|
44
44
|
],
|
|
45
|
-
"author": "
|
|
45
|
+
"author": "javadrostami",
|
|
46
46
|
"license": "MIT",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/JavadRostami3/llm-retry-kit.git"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/JavadRostami3/llm-retry-kit/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/JavadRostami3/llm-retry-kit#readme",
|
|
47
55
|
"devDependencies": {
|
|
48
56
|
"typescript": "^5.4.0",
|
|
49
57
|
"vitest": "^4.1.8"
|