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 CHANGED
@@ -1,14 +1,52 @@
1
1
  # llm-retry-kit
2
2
 
3
- Smart retry wrapper for LLM APIs. It handles transient failures, rate limits,
4
- fallback calls, exponential backoff, and simple token-cost tracking.
3
+ [![npm](https://img.shields.io/npm/v/llm-retry-kit?label=npm)](https://www.npmjs.com/package/llm-retry-kit)
4
+ [![downloads](https://img.shields.io/npm/dm/llm-retry-kit?label=downloads)](https://www.npmjs.com/package/llm-retry-kit)
5
+ [![license](https://img.shields.io/npm/l/llm-retry-kit?label=license)](./LICENSE)
6
+ [![node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](./package.json)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue)](./tsconfig.json)
8
+ [![CI](https://img.shields.io/github/actions/workflow/status/JavadRostami3/llm-retry-kit/ci.yml?label=CI)](https://github.com/JavadRostami3/llm-retry-kit/actions)
5
9
 
6
- ## Install
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
- model: 'gpt-4o-mini',
24
- messages: [{ role: 'user', content: 'Hello!' }],
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: 3,
54
- initialDelayMs: 1000,
55
- maxDelayMs: 30000,
180
+ maxRetries: 2,
56
181
  })
182
+ ```
57
183
 
58
- if (result.usedFallback) {
59
- console.log('Fallback model was used')
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
- ## Budget Tracking
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
- `llm-retry-kit` tracks cost from the `usage.totalTokens` value returned by your
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
- ## Retry Logging
228
+ For real provider pricing, prefer `costCalculator`:
82
229
 
83
230
  ```ts
84
231
  const result = await llmRetry({
85
232
  fn: myLLMCall,
86
- maxRetries: 4,
87
- initialDelayMs: 1000,
88
- maxDelayMs: 60000,
89
- onRetry: (attempt, error, delayMs) => {
90
- console.log(`Attempt ${attempt} failed: ${error.message}`)
91
- console.log(`Waiting ${(delayMs / 1000).toFixed(1)}s before retrying`)
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
- ## API
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>>` | required | Primary async LLM call. |
103
- | `fallback` | `() => Promise<LLMResponse<T>>` | optional | Backup async LLM call. |
104
- | `maxRetries` | `number` | `3` | Number of retries after the first attempt. |
105
- | `maxCostUSD` | `number` | optional | Maximum tracked cost in USD. |
106
- | `costPer1kTokens` | `number` | `0.002` | Estimated cost per 1,000 tokens. |
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
- | `onRetry` | `(attempt, error, delayMs) => void` | optional | Called before each retry wait. |
110
- | `onBudgetExceeded` | `(spentUSD, limitUSD) => void` | optional | Called when tracked budget is exhausted. |
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
- ### `LLMResponse<T>`
332
+ ### `RetryProvider<T>`
113
333
 
114
334
  ```ts
115
335
  {
116
- data: T
117
- usage?: {
118
- promptTokens: number
119
- completionTokens: number
120
- totalTokens: number
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
- ## Retryable Errors
357
+ ### `LLMRetryError`
138
358
 
139
- The package retries common transient failures:
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
- - HTTP `429`
142
- - HTTP `5xx`
143
- - timeout errors
144
- - network connection errors
145
- - overloaded server errors
384
+ ## Development
146
385
 
147
- Authentication errors, invalid requests, and other non-transient failures are
148
- not retried.
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
@@ -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,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAiDxD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyB/D"}
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
- return new Promise((resolve) => setTimeout(resolve, ms));
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 === 429 || (status !== null && status >= 500 && status <= 599)) {
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 headerValue = getHeader(err['headers'], 'retry-after');
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 seconds = Number(headerValue);
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
- const dateMs = Date.parse(headerValue);
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;
@@ -1 +1 @@
1
- {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../src/backoff.ts"],"names":[],"mappings":"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"}
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;
@@ -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;IAK5B,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"}
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 += (usage.totalTokens / 1000) * this.costPer1kTokens;
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)
@@ -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;QACnB,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAA;QACrC,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe,CAAA;IACxE,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"}
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 { RetryOptions, RetryResult, TokenUsage, LLMResponse, RetryableError, } from './types.js';
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
@@ -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;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACjE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,cAAc,GACf,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;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,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
- constructor(message: string, primaryError: Error | null, fallbackError: Error | null, totalCostUSD: number, totalTokens: number);
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
@@ -1 +1 @@
1
- {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE3D,wBAAsB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAgHnF;AAeD,qBAAa,aAAc,SAAQ,KAAK;aAGpB,YAAY,EAAE,KAAK,GAAG,IAAI;aAC1B,aAAa,EAAE,KAAK,GAAG,IAAI;aAC3B,YAAY,EAAE,MAAM;aACpB,WAAW,EAAE,MAAM;gBAJnC,OAAO,EAAE,MAAM,EACC,YAAY,EAAE,KAAK,GAAG,IAAI,EAC1B,aAAa,EAAE,KAAK,GAAG,IAAI,EAC3B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM;CAKtC"}
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 { fn, fallback, maxRetries = 3, maxCostUSD, costPer1kTokens = 0.002, initialDelayMs = 1000, maxDelayMs = 30000, onRetry, onBudgetExceeded, } = options;
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
- let lastError = null;
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
- for (let retryIndex = 0; retryIndex <= maxRetries; retryIndex++) {
11
- if (budget.isExceeded()) {
12
- budgetExceededNotified = notifyBudgetExceeded(budget.spent, budget.limit, onBudgetExceeded, budgetExceededNotified);
13
- break;
14
- }
15
- attempts += 1;
16
- try {
17
- const response = await fn();
18
- if (response.usage) {
19
- budget.add(response.usage);
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
- return {
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
- if (fallback && !budget.isExceeded()) {
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
- catch (fallbackError) {
58
- const err = fallbackError instanceof Error
59
- ? fallbackError
60
- : new Error(String(fallbackError));
61
- throw new LLMRetryError(`Both primary and fallback failed. Primary: ${lastError?.message ?? 'unknown error'}. Fallback: ${err.message}`, lastError, err, budget.spent, budget.tokens);
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
- if (budget.isExceeded()) {
65
- notifyBudgetExceeded(budget.spent, budget.limit, onBudgetExceeded, budgetExceededNotified);
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
- throw new LLMRetryError(`LLM call failed after ${attempts} attempt${attempts === 1 ? '' : 's'}: ${lastError?.message ?? 'budget exceeded'}`, lastError, null, budget.spent, budget.tokens);
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
- constructor(message, primaryError, fallbackError, totalCostUSD, totalTokens) {
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":"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"}
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: () => Promise<LLMResponse<T>>;
12
- fallback?: () => Promise<LLMResponse<T>>;
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
- onRetry?: (attempt: number, error: Error, delayMs: number) => void;
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
@@ -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,GAAG,OAAO;IACvC,EAAE,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IACxC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAClE,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,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,CAAA"}
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.0",
4
- "description": "Smart retry wrapper for LLM APIs with fallback, budget tracking, and exponential backoff.",
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": "llm-retry contributors",
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"