ai-retry 0.0.1-alpha.2 → 0.0.1-alpha.3
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 +112 -76
- package/dist/create-retryable-model-DKKgxKLw.d.ts +42 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +49 -21
- package/dist/retryables/index.d.ts +1 -1
- package/dist/retryables/index.js +4 -4
- package/package.json +1 -1
- package/dist/create-retryable-model-Ddjfs7Y2.d.ts +0 -29
package/README.md
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
🚧 **WORK IN PROGRESS - DO NOT USE IN PRODUCTION**
|
|
1
|
+
### ai-retry
|
|
4
2
|
|
|
5
3
|
Intelligent retry and fallback mechanisms for AI SDK models. Automatically handle API failures, content filtering, timeouts, and schema mismatches by switching between different AI models.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
#### How?
|
|
6
|
+
|
|
7
|
+
`ai-retry` wraps the provided base model with a set of retry conditions (retryables). When a request fails due to specific errors (like content filtering or timeouts), it iterates through the given retryables to find a suitable fallback model. It automatically tracks which models have been tried and how many attempts have been made to prevent infinite loops.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### Installation
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
This library only supports AI SDK v5.
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
> `ai-retry` is in alpha stage and the API may change in future releases.
|
|
12
15
|
|
|
13
16
|
```bash
|
|
14
|
-
npm install ai-retry
|
|
15
|
-
# or
|
|
16
|
-
pnpm add ai-retry
|
|
17
|
-
# or
|
|
18
|
-
yarn add ai-retry
|
|
17
|
+
npm install ai-retry@alpha
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
### Usage
|
|
21
|
+
|
|
22
|
+
Create a retryable model by providing a base model and a list of retryables or fallback models.
|
|
23
|
+
|
|
24
|
+
> [!WARNING]
|
|
25
|
+
> `ai-retry` currently only supports `generateText` and `generateObject` calls.
|
|
26
|
+
> Streaming via `streamText` and `streamObject` is not supported yet.
|
|
22
27
|
|
|
23
28
|
```typescript
|
|
24
29
|
import { azure } from '@ai-sdk/azure';
|
|
@@ -47,35 +52,21 @@ const result = await generateText({
|
|
|
47
52
|
});
|
|
48
53
|
```
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
If you always want to fallback to a different model on any error, you can simply provide a list of models:
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
const retryableModel = createRetryable({
|
|
56
|
-
model: azure('gpt-4'),
|
|
57
|
-
retries: [
|
|
58
|
-
openai('gpt-4'),
|
|
59
|
-
anthropic('claude-3-haiku-20240307')
|
|
60
|
-
],
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Retryables
|
|
55
|
+
#### Retryables
|
|
65
56
|
|
|
66
|
-
A retryable is a function that receives
|
|
67
|
-
|
|
57
|
+
A retryable is a function that receives the current failed attempt and determines whether to retry with a different model based on the error and any previous attempts.
|
|
58
|
+
There are several built-in retryables:
|
|
68
59
|
|
|
69
|
-
- `contentFilterTriggered`:
|
|
70
|
-
- `responseSchemaMismatch`:
|
|
71
|
-
- `requestTimeout`:
|
|
72
|
-
- `requestNotRetryable`:
|
|
60
|
+
- `contentFilterTriggered`: Content filter was triggered based on the prompt or completion.
|
|
61
|
+
- `responseSchemaMismatch`: Structured output validation failed.
|
|
62
|
+
- `requestTimeout`: Request timeout occurred.
|
|
63
|
+
- `requestNotRetryable`: Request failed with a non-retryable error.
|
|
73
64
|
|
|
74
65
|
By default, each retryable will only attempt to retry once per model to avoid infinite loops. You can customize this behavior by returning a `maxAttempts` value from your retryable function.
|
|
75
66
|
|
|
76
|
-
|
|
67
|
+
##### Content Filter Triggered
|
|
77
68
|
|
|
78
|
-
Automatically switch to a different model when content filtering blocks your request
|
|
69
|
+
Automatically switch to a different model when content filtering blocks your request.
|
|
79
70
|
|
|
80
71
|
```typescript
|
|
81
72
|
import { contentFilterTriggered } from 'ai-retry/retryables';
|
|
@@ -88,7 +79,7 @@ const retryableModel = createRetryable({
|
|
|
88
79
|
});
|
|
89
80
|
```
|
|
90
81
|
|
|
91
|
-
|
|
82
|
+
##### Response Schema Mismatch
|
|
92
83
|
|
|
93
84
|
Retry with different models when structured output validation fails:
|
|
94
85
|
|
|
@@ -98,7 +89,7 @@ import { responseSchemaMismatch } from 'ai-retry/retryables';
|
|
|
98
89
|
const retryableModel = createRetryable({
|
|
99
90
|
model: azure('gpt-4-mini'),
|
|
100
91
|
retries: [
|
|
101
|
-
responseSchemaMismatch(azure('gpt-4')), // Try full model for better
|
|
92
|
+
responseSchemaMismatch(azure('gpt-4')), // Try full model for better structured output
|
|
102
93
|
],
|
|
103
94
|
});
|
|
104
95
|
|
|
@@ -115,9 +106,12 @@ const result = await generateObject({
|
|
|
115
106
|
});
|
|
116
107
|
```
|
|
117
108
|
|
|
118
|
-
|
|
109
|
+
##### Request Timeout
|
|
119
110
|
|
|
120
|
-
Handle timeouts by switching to potentially faster models
|
|
111
|
+
Handle timeouts by switching to potentially faster models.
|
|
112
|
+
|
|
113
|
+
> [!NOTE]
|
|
114
|
+
> You need to set an `abortSignal` with a timeout on your request for this to work.
|
|
121
115
|
|
|
122
116
|
```typescript
|
|
123
117
|
import { requestTimeout } from 'ai-retry/retryables';
|
|
@@ -136,9 +130,9 @@ const result = await generateText({
|
|
|
136
130
|
});
|
|
137
131
|
```
|
|
138
132
|
|
|
139
|
-
|
|
133
|
+
##### Request Not Retryable
|
|
140
134
|
|
|
141
|
-
Handle cases where the base model fails with a non-retryable error
|
|
135
|
+
Handle cases where the base model fails with a non-retryable error.
|
|
142
136
|
|
|
143
137
|
```typescript
|
|
144
138
|
import { requestNotRetryable } from 'ai-retry/retryables';
|
|
@@ -151,7 +145,7 @@ const retryable = createRetryable({
|
|
|
151
145
|
});
|
|
152
146
|
```
|
|
153
147
|
|
|
154
|
-
|
|
148
|
+
##### Custom Retryables
|
|
155
149
|
|
|
156
150
|
Create your own retryables for specific use cases:
|
|
157
151
|
|
|
@@ -159,10 +153,10 @@ Create your own retryables for specific use cases:
|
|
|
159
153
|
import type { Retryable } from 'ai-retry';
|
|
160
154
|
|
|
161
155
|
const customRetry: Retryable = (context) => {
|
|
162
|
-
const {
|
|
156
|
+
const { current, attempts, totalAttempts } = context;
|
|
163
157
|
|
|
164
158
|
// Your custom logic here
|
|
165
|
-
if (shouldRetryWithDifferentModel(error)) {
|
|
159
|
+
if (shouldRetryWithDifferentModel(current.error)) {
|
|
166
160
|
return {
|
|
167
161
|
model: myFallbackModel,
|
|
168
162
|
maxAttempts: 3,
|
|
@@ -178,24 +172,73 @@ const retryable = createRetryable({
|
|
|
178
172
|
});
|
|
179
173
|
```
|
|
180
174
|
|
|
181
|
-
|
|
175
|
+
#### Default Fallback
|
|
182
176
|
|
|
183
|
-
|
|
177
|
+
If you always want to fallback to a different model on any error, you can simply provide a list of models.
|
|
184
178
|
|
|
185
179
|
```typescript
|
|
186
|
-
const
|
|
187
|
-
model:
|
|
180
|
+
const retryableModel = createRetryable({
|
|
181
|
+
model: azure('gpt-4'),
|
|
182
|
+
retries: [
|
|
183
|
+
openai('gpt-4'),
|
|
184
|
+
anthropic('claude-3-haiku-20240307')
|
|
185
|
+
],
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### All Retries Failed
|
|
190
|
+
|
|
191
|
+
If all retry attempts failed, a `RetryError` is thrown containing all individual errors.
|
|
192
|
+
If no retry was attempted (e.g. because all retryables returned `undefined`), the original error is thrown directly.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { RetryError } from 'ai';
|
|
196
|
+
|
|
197
|
+
const retryableModel = createRetryable({
|
|
198
|
+
model: azure('gpt-4'),
|
|
199
|
+
retries: [
|
|
200
|
+
openai('gpt-4'),
|
|
201
|
+
anthropic('claude-3-haiku-20240307')
|
|
202
|
+
],
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
const result = await generateText({
|
|
207
|
+
model: retryableModel,
|
|
208
|
+
prompt: 'Hello world!',
|
|
209
|
+
});
|
|
210
|
+
} catch (error) {
|
|
211
|
+
// RetryError is an official AI SDK error
|
|
212
|
+
if (error instanceof RetryError) {
|
|
213
|
+
console.error('All retry attempts failed:', error.errors);
|
|
214
|
+
} else {
|
|
215
|
+
console.error('Request failed:', error);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### Logging
|
|
221
|
+
|
|
222
|
+
You can use the following callbacks to log retry attempts and errors:
|
|
223
|
+
- `onError` is invoked if an error occurs.
|
|
224
|
+
- `onRetry` is invoked before attempting a retry.
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const retryableModel = createRetryable({
|
|
228
|
+
model: openai('gpt-4-mini'),
|
|
188
229
|
retries: [/* your retryables */],
|
|
189
230
|
onError: (context) => {
|
|
190
|
-
console.log(`Attempt ${context.totalAttempts} failed:`, context.error);
|
|
191
|
-
|
|
231
|
+
console.log(`Attempt ${context.totalAttempts} with ${context.current.model.provider}/${context.current.model.modelId} failed:`, context.current.error);
|
|
232
|
+
},
|
|
233
|
+
onRetry: (context) => {
|
|
234
|
+
console.log(`Retrying with model ${context.current.model.provider}/${context.current.model.modelId}...`);
|
|
192
235
|
},
|
|
193
236
|
});
|
|
194
237
|
```
|
|
195
238
|
|
|
196
|
-
|
|
239
|
+
### API Reference
|
|
197
240
|
|
|
198
|
-
|
|
241
|
+
#### `createRetryable(options: CreateRetryableOptions): LanguageModelV2`
|
|
199
242
|
|
|
200
243
|
Creates a retryable language model.
|
|
201
244
|
|
|
@@ -204,21 +247,23 @@ interface CreateRetryableOptions {
|
|
|
204
247
|
model: LanguageModelV2;
|
|
205
248
|
retries: Array<Retryable | LanguageModelV2>;
|
|
206
249
|
onError?: (context: RetryContext) => void;
|
|
250
|
+
onRetry?: (context: RetryContext) => void;
|
|
207
251
|
}
|
|
208
252
|
```
|
|
209
253
|
|
|
210
|
-
|
|
254
|
+
#### `Retryable`
|
|
211
255
|
|
|
212
|
-
A `Retryable` is a function that receives a `RetryContext` with the current error and model and all
|
|
213
|
-
It should evaluate the error and decide whether to retry by returning a
|
|
256
|
+
A `Retryable` is a function that receives a `RetryContext` with the current error and model and all previous attempts.
|
|
257
|
+
It should evaluate the error and decide whether to retry by returning a `RetryModel` or to skip by returning `undefined`.
|
|
214
258
|
|
|
215
259
|
```ts
|
|
216
260
|
type Retryable = (context: RetryContext) => RetryModel | Promise<RetryModel> | undefined;
|
|
217
261
|
```
|
|
218
262
|
|
|
219
|
-
|
|
263
|
+
#### `RetryModel`
|
|
220
264
|
|
|
221
|
-
A `RetryModel` specifies the model to retry
|
|
265
|
+
A `RetryModel` specifies the model to retry and an optional `maxAttempts` to limit how many times this model can be retried.
|
|
266
|
+
By default, each retryable will only attempt to retry once per model. This can be customized by setting the `maxAttempts` property.
|
|
222
267
|
|
|
223
268
|
```typescript
|
|
224
269
|
interface RetryModel {
|
|
@@ -227,38 +272,29 @@ interface RetryModel {
|
|
|
227
272
|
}
|
|
228
273
|
```
|
|
229
274
|
|
|
230
|
-
|
|
275
|
+
#### `RetryContext`
|
|
231
276
|
|
|
232
|
-
The `RetryContext` object contains information about the current
|
|
277
|
+
The `RetryContext` object contains information about the current attempt and all previous attempts.
|
|
233
278
|
|
|
234
279
|
```typescript
|
|
235
280
|
interface RetryContext {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
triedModels: Map<string, RetryState>;
|
|
240
|
-
totalAttempts: number;
|
|
281
|
+
current: RetryAttempt;
|
|
282
|
+
attempts: Array<RetryAttempt>;
|
|
283
|
+
totalAttempts: number;
|
|
241
284
|
}
|
|
242
285
|
```
|
|
243
286
|
|
|
244
|
-
|
|
287
|
+
#### `RetryAttempt`
|
|
245
288
|
|
|
246
|
-
|
|
289
|
+
A `RetryAttempt` represents a single failed attempt with a specific model.
|
|
247
290
|
|
|
248
291
|
```typescript
|
|
249
|
-
interface
|
|
250
|
-
|
|
292
|
+
interface RetryAttempt {
|
|
293
|
+
error: unknown;
|
|
251
294
|
model: LanguageModelV2;
|
|
252
|
-
attempts: number;
|
|
253
|
-
errors: Array<unknown>;
|
|
254
295
|
}
|
|
255
296
|
```
|
|
256
297
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
- AI SDK v2.0+
|
|
260
|
-
- Node.js 16+
|
|
261
|
-
|
|
262
|
-
## License
|
|
298
|
+
### License
|
|
263
299
|
|
|
264
300
|
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LanguageModelV2 } from "@ai-sdk/provider";
|
|
2
|
+
|
|
3
|
+
//#region src/create-retryable-model.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The context provided to Retryables with the current attempt and all previous attempts.
|
|
7
|
+
*/
|
|
8
|
+
interface RetryContext {
|
|
9
|
+
current: RetryAttempt;
|
|
10
|
+
attempts: Array<RetryAttempt>;
|
|
11
|
+
totalAttempts: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A retry attempt with the error and model used
|
|
15
|
+
*/
|
|
16
|
+
interface RetryAttempt {
|
|
17
|
+
error: unknown;
|
|
18
|
+
model: LanguageModelV2;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A model to retry with and the maximum number of attempts for that model.
|
|
22
|
+
*/
|
|
23
|
+
type RetryModel = {
|
|
24
|
+
model: LanguageModelV2;
|
|
25
|
+
maxAttempts: number;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A function that determines whether to retry with a different model based on the current attempt and all previous attempts.
|
|
29
|
+
*/
|
|
30
|
+
type Retryable = (context: RetryContext) => RetryModel | Promise<RetryModel> | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Options for creating a retryable model.
|
|
33
|
+
*/
|
|
34
|
+
interface CreateRetryableOptions {
|
|
35
|
+
model: LanguageModelV2;
|
|
36
|
+
retries: Array<Retryable | LanguageModelV2>;
|
|
37
|
+
onError?: (context: RetryContext) => void;
|
|
38
|
+
onRetry?: (context: RetryContext) => void;
|
|
39
|
+
}
|
|
40
|
+
declare function createRetryable(config: CreateRetryableOptions): LanguageModelV2;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { CreateRetryableOptions, RetryAttempt, RetryContext, RetryModel, Retryable, createRetryable };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateRetryableOptions, RetryContext, RetryModel,
|
|
1
|
+
import { CreateRetryableOptions, RetryAttempt, RetryContext, RetryModel, Retryable, createRetryable } from "./create-retryable-model-DKKgxKLw.js";
|
|
2
2
|
import { LanguageModelV2 } from "@ai-sdk/provider";
|
|
3
3
|
|
|
4
4
|
//#region src/get-model-key.d.ts
|
|
@@ -7,4 +7,4 @@ import { LanguageModelV2 } from "@ai-sdk/provider";
|
|
|
7
7
|
*/
|
|
8
8
|
declare const getModelKey: (model: LanguageModelV2) => string;
|
|
9
9
|
//#endregion
|
|
10
|
-
export { CreateRetryableOptions, RetryContext, RetryModel,
|
|
10
|
+
export { CreateRetryableOptions, RetryAttempt, RetryContext, RetryModel, Retryable, createRetryable, getModelKey };
|
package/dist/index.js
CHANGED
|
@@ -46,34 +46,60 @@ var RetryableModel = class {
|
|
|
46
46
|
*/
|
|
47
47
|
let totalAttempts = 0;
|
|
48
48
|
/**
|
|
49
|
-
* Track
|
|
49
|
+
* Track all attempts.
|
|
50
50
|
*/
|
|
51
|
-
const
|
|
51
|
+
const attempts = [];
|
|
52
|
+
/**
|
|
53
|
+
* The error occured in the previous attempt or undefined if this is the first attempt
|
|
54
|
+
*/
|
|
55
|
+
let currentError;
|
|
52
56
|
while (true) {
|
|
53
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Call the onRetry handler if provided.
|
|
59
|
+
* Skip on the first attempt since no error occured yet.
|
|
60
|
+
*/
|
|
61
|
+
if (currentError) {
|
|
62
|
+
/**
|
|
63
|
+
* Context for the onRetry handler
|
|
64
|
+
*/
|
|
65
|
+
const context = {
|
|
66
|
+
current: {
|
|
67
|
+
error: currentError,
|
|
68
|
+
model: this.currentModel
|
|
69
|
+
},
|
|
70
|
+
attempts,
|
|
71
|
+
totalAttempts
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Call the onRetry handler if provided
|
|
75
|
+
*/
|
|
76
|
+
this.options.onRetry?.(context);
|
|
77
|
+
}
|
|
54
78
|
try {
|
|
79
|
+
totalAttempts++;
|
|
55
80
|
return await this.currentModel.doGenerate(options);
|
|
56
81
|
} catch (error) {
|
|
57
|
-
const currentModelKey = getModelKey(this.currentModel);
|
|
58
|
-
const prevState = triedModels.get(currentModelKey);
|
|
59
82
|
/**
|
|
60
|
-
* Save
|
|
83
|
+
* Save the error of the current attempt for the retry of the next iteration
|
|
84
|
+
*/
|
|
85
|
+
currentError = error;
|
|
86
|
+
/**
|
|
87
|
+
* Current attempt with current error
|
|
61
88
|
*/
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
model: this.currentModel
|
|
65
|
-
attempts: (prevState?.attempts ?? 0) + 1,
|
|
66
|
-
errors: [...prevState?.errors ?? [], error]
|
|
89
|
+
const currentAttempt = {
|
|
90
|
+
error: currentError,
|
|
91
|
+
model: this.currentModel
|
|
67
92
|
};
|
|
68
|
-
triedModels.set(currentModelKey, newState);
|
|
69
93
|
/**
|
|
70
|
-
*
|
|
94
|
+
* Save the current attempt
|
|
95
|
+
*/
|
|
96
|
+
attempts.push(currentAttempt);
|
|
97
|
+
/**
|
|
98
|
+
* Context for the retryables and onError handler
|
|
71
99
|
*/
|
|
72
100
|
const context = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
currentModel: this.currentModel,
|
|
76
|
-
triedModels,
|
|
101
|
+
current: currentAttempt,
|
|
102
|
+
attempts,
|
|
77
103
|
totalAttempts
|
|
78
104
|
};
|
|
79
105
|
/**
|
|
@@ -87,12 +113,14 @@ var RetryableModel = class {
|
|
|
87
113
|
for (const retry of this.options.retries) {
|
|
88
114
|
const retryModel = typeof retry === "function" ? await retry(context) : defaultRetryModel(retry);
|
|
89
115
|
if (retryModel) {
|
|
116
|
+
/**
|
|
117
|
+
* The model key uniquely identifies a model instance (provider + modelId)
|
|
118
|
+
*/
|
|
90
119
|
const retryModelKey = getModelKey(retryModel.model);
|
|
91
|
-
const retryState = triedModels.get(retryModelKey);
|
|
92
120
|
/**
|
|
93
121
|
* Check if the model can still be retried based on maxAttempts
|
|
94
122
|
*/
|
|
95
|
-
if (
|
|
123
|
+
if (attempts.filter((a) => getModelKey(a.model) === retryModelKey).length < retryModel.maxAttempts) {
|
|
96
124
|
nextModel = retryModel.model;
|
|
97
125
|
break;
|
|
98
126
|
}
|
|
@@ -105,11 +133,11 @@ var RetryableModel = class {
|
|
|
105
133
|
if (!nextModel) {
|
|
106
134
|
if (totalAttempts > 1) {
|
|
107
135
|
const errorMessage = getErrorMessage(error);
|
|
108
|
-
const
|
|
136
|
+
const errors = attempts.flatMap((a) => a.error);
|
|
109
137
|
throw new RetryError({
|
|
110
138
|
message: `Failed after ${totalAttempts} attempts. Last error: ${errorMessage}`,
|
|
111
139
|
reason: "maxRetriesExceeded",
|
|
112
|
-
errors
|
|
140
|
+
errors
|
|
113
141
|
});
|
|
114
142
|
}
|
|
115
143
|
throw error;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RetryModel, Retryable } from "../create-retryable-model-
|
|
1
|
+
import { RetryModel, Retryable } from "../create-retryable-model-DKKgxKLw.js";
|
|
2
2
|
import { LanguageModelV2 } from "@ai-sdk/provider";
|
|
3
3
|
|
|
4
4
|
//#region src/retryables/content-filter-triggered.d.ts
|
package/dist/retryables/index.js
CHANGED
|
@@ -13,7 +13,7 @@ const isString = (value) => typeof value === "string";
|
|
|
13
13
|
*/
|
|
14
14
|
function contentFilterTriggered(input) {
|
|
15
15
|
return (context) => {
|
|
16
|
-
const { error } = context;
|
|
16
|
+
const { error } = context.current;
|
|
17
17
|
const model = "model" in input ? input.model : input;
|
|
18
18
|
if (APICallError.isInstance(error) && isObject(error.data) && isObject(error.data.error) && isString(error.data.error.code) && error.data.error.code === "content_filter") return {
|
|
19
19
|
model,
|
|
@@ -33,7 +33,7 @@ function contentFilterTriggered(input) {
|
|
|
33
33
|
*/
|
|
34
34
|
function requestNotRetryable(input) {
|
|
35
35
|
return (context) => {
|
|
36
|
-
const { error } = context;
|
|
36
|
+
const { error } = context.current;
|
|
37
37
|
const model = "model" in input ? input.model : input;
|
|
38
38
|
if (APICallError$1.isInstance(error) && error.isRetryable === false) return {
|
|
39
39
|
model,
|
|
@@ -50,7 +50,7 @@ function requestNotRetryable(input) {
|
|
|
50
50
|
*/
|
|
51
51
|
function requestTimeout(input) {
|
|
52
52
|
return (context) => {
|
|
53
|
-
const { error } = context;
|
|
53
|
+
const { error } = context.current;
|
|
54
54
|
const model = "model" in input ? input.model : input;
|
|
55
55
|
/**
|
|
56
56
|
* Fallback to the specified model after all retries are exhausted.
|
|
@@ -66,7 +66,7 @@ function requestTimeout(input) {
|
|
|
66
66
|
//#region src/retryables/response-schema-mismatch.ts
|
|
67
67
|
function responseSchemaMismatch(input) {
|
|
68
68
|
return (context) => {
|
|
69
|
-
const { error } = context;
|
|
69
|
+
const { error } = context.current;
|
|
70
70
|
const model = "model" in input ? input.model : input;
|
|
71
71
|
if (NoObjectGeneratedError.isInstance(error) && error.finishReason === "stop" && TypeValidationError.isInstance(error.cause)) return {
|
|
72
72
|
model,
|
package/package.json
CHANGED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { LanguageModelV2 } from "@ai-sdk/provider";
|
|
2
|
-
|
|
3
|
-
//#region src/create-retryable-model.d.ts
|
|
4
|
-
interface RetryContext {
|
|
5
|
-
error: unknown;
|
|
6
|
-
baseModel: LanguageModelV2;
|
|
7
|
-
currentModel: LanguageModelV2;
|
|
8
|
-
triedModels: Map<string, RetryState>;
|
|
9
|
-
totalAttempts: number;
|
|
10
|
-
}
|
|
11
|
-
type RetryModel = {
|
|
12
|
-
model: LanguageModelV2;
|
|
13
|
-
maxAttempts: number;
|
|
14
|
-
};
|
|
15
|
-
type Retryable = (context: RetryContext) => RetryModel | Promise<RetryModel> | undefined;
|
|
16
|
-
type RetryState = {
|
|
17
|
-
modelKey: string;
|
|
18
|
-
model: LanguageModelV2;
|
|
19
|
-
attempts: number;
|
|
20
|
-
errors: Array<unknown>;
|
|
21
|
-
};
|
|
22
|
-
interface CreateRetryableOptions {
|
|
23
|
-
model: LanguageModelV2;
|
|
24
|
-
retries: Array<Retryable | LanguageModelV2>;
|
|
25
|
-
onError?: (context: RetryContext) => void;
|
|
26
|
-
}
|
|
27
|
-
declare function createRetryable(config: CreateRetryableOptions): LanguageModelV2;
|
|
28
|
-
//#endregion
|
|
29
|
-
export { CreateRetryableOptions, RetryContext, RetryModel, RetryState, Retryable, createRetryable };
|