ai-retry 1.2.0 → 1.3.0
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 +87 -34
- package/dist/index.d.mts +7 -5
- package/dist/index.mjs +168 -7
- package/dist/retryables/index.d.mts +13 -7
- package/dist/retryables/index.mjs +22 -3
- package/dist/{types-Dk5KMZMd.d.mts → types-wEZKtEcH.d.mts} +21 -14
- package/dist/{utils-fYGELi1C.mjs → utils-CfnsSGrw.mjs} +4 -3
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Create a retryable model by providing a base model and a list of retryables or f
|
|
|
41
41
|
When an error occurs, it will evaluate each retryable in order and use the first one that indicates a retry should be attempted with a different model.
|
|
42
42
|
|
|
43
43
|
> [!NOTE]
|
|
44
|
-
> `ai-retry` supports
|
|
44
|
+
> `ai-retry` supports language models, embedding models, and image models.
|
|
45
45
|
|
|
46
46
|
```typescript
|
|
47
47
|
import { openai } from '@ai-sdk/openai';
|
|
@@ -101,6 +101,28 @@ const result = await embed({
|
|
|
101
101
|
console.log(result.embedding);
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
This also works with image models:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { openai } from '@ai-sdk/openai';
|
|
108
|
+
import { generateImage } from 'ai';
|
|
109
|
+
import { createRetryable } from 'ai-retry';
|
|
110
|
+
|
|
111
|
+
const retryableModel = createRetryable({
|
|
112
|
+
model: openai.image('dall-e-3'),
|
|
113
|
+
retries: [
|
|
114
|
+
// Retry strategies and fallbacks...
|
|
115
|
+
],
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const result = await generateImage({
|
|
119
|
+
model: retryableModel,
|
|
120
|
+
prompt: 'A sunset over mountains',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
console.log(result.images);
|
|
124
|
+
```
|
|
125
|
+
|
|
104
126
|
#### Vercel AI Gateway
|
|
105
127
|
|
|
106
128
|
You can use `ai-retry` with Vercel AI Gateway by providing the model as a string. Internally, the model will be resolved with the default `gateway` [provider instance](https://ai-sdk.dev/providers/ai-sdk-providers/ai-gateway#provider-instance) from AI SDK.
|
|
@@ -356,9 +378,9 @@ There are several built-in dynamic retryables available for common use cases:
|
|
|
356
378
|
- [`requestNotRetryable`](./src/retryables/request-not-retryable.ts): Request failed with a non-retryable error.
|
|
357
379
|
- [`retryAfterDelay`](./src/retryables/retry-after-delay.ts): Retry with delay and exponential backoff and respect `retry-after` headers.
|
|
358
380
|
- [`serviceOverloaded`](./src/retryables/service-overloaded.ts): Response with status code 529 (service overloaded).
|
|
359
|
-
- Use this retryable to handle Anthropic's overloaded errors.
|
|
360
381
|
- [`serviceUnavailable`](./src/retryables/service-unavailable.ts): Response with status code 503 (service unavailable).
|
|
361
382
|
- [`schemaMismatch`](./src/retryables/schema-mismatch.ts): Response JSON doesn't match the expected schema from structured output modes (`Output.object()`, `Output.array()`, `Output.choice()`).
|
|
383
|
+
- [`noImageGenerated`](./src/retryables/no-image-generated.ts): Image generation failed with `NoImageGeneratedError`.
|
|
362
384
|
|
|
363
385
|
#### Content Filter
|
|
364
386
|
|
|
@@ -412,9 +434,6 @@ const result = await generateText({
|
|
|
412
434
|
|
|
413
435
|
Handle service overload errors (status code 529) by switching to a provider.
|
|
414
436
|
|
|
415
|
-
> [!NOTE]
|
|
416
|
-
> You can use this retryable to handle Anthropic's overloaded errors.
|
|
417
|
-
|
|
418
437
|
```typescript
|
|
419
438
|
import { serviceOverloaded } from 'ai-retry/retryables';
|
|
420
439
|
|
|
@@ -453,6 +472,29 @@ const retryableModel = createRetryable({
|
|
|
453
472
|
});
|
|
454
473
|
```
|
|
455
474
|
|
|
475
|
+
#### No Image Generated
|
|
476
|
+
|
|
477
|
+
Handle image generation failures by switching to a different model.
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
import { openai } from '@ai-sdk/openai';
|
|
481
|
+
import { generateImage } from 'ai';
|
|
482
|
+
import { createRetryable } from 'ai-retry';
|
|
483
|
+
import { noImageGenerated } from 'ai-retry/retryables';
|
|
484
|
+
|
|
485
|
+
const retryableModel = createRetryable({
|
|
486
|
+
model: openai.image('dall-e-3'),
|
|
487
|
+
retries: [
|
|
488
|
+
noImageGenerated(openai.image('dall-e-2')), // Fallback to DALL-E 2
|
|
489
|
+
],
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
const result = await generateImage({
|
|
493
|
+
model: retryableModel,
|
|
494
|
+
prompt: 'A sunset over mountains',
|
|
495
|
+
});
|
|
496
|
+
```
|
|
497
|
+
|
|
456
498
|
#### Request Not Retryable
|
|
457
499
|
|
|
458
500
|
Handle cases where the base model fails with a non-retryable error.
|
|
@@ -736,6 +778,17 @@ The following options can be overridden:
|
|
|
736
778
|
| [`headers`](https://ai-sdk.dev/docs/reference/ai-sdk-core/embed#headers) | Additional HTTP headers |
|
|
737
779
|
| [`providerOptions`](https://ai-sdk.dev/docs/reference/ai-sdk-core/embed#provideroptions) | Provider-specific options |
|
|
738
780
|
|
|
781
|
+
##### Image Model Options
|
|
782
|
+
|
|
783
|
+
| Option | Description |
|
|
784
|
+
|--------|-------------|
|
|
785
|
+
| [`n`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#n) | Number of images to generate |
|
|
786
|
+
| [`size`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#size) | Size of generated images |
|
|
787
|
+
| [`aspectRatio`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#aspectratio) | Aspect ratio of generated images |
|
|
788
|
+
| [`seed`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#seed) | Random seed for reproducibility |
|
|
789
|
+
| [`headers`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#headers) | Additional HTTP headers |
|
|
790
|
+
| [`providerOptions`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#provideroptions) | Provider-specific options |
|
|
791
|
+
|
|
739
792
|
#### Logging
|
|
740
793
|
|
|
741
794
|
You can use the following callbacks to log retry attempts and errors:
|
|
@@ -763,21 +816,21 @@ By default, every new request starts with the base model, even if a previous req
|
|
|
763
816
|
|
|
764
817
|
| Value | Description |
|
|
765
818
|
|-------|-------------|
|
|
766
|
-
| `
|
|
767
|
-
|
|
|
768
|
-
|
|
|
819
|
+
| `after-request` | Reset immediately after the next request (default) |
|
|
820
|
+
| `after-N-requests` | Keep the retry model for the next **N** requests, then reset |
|
|
821
|
+
| `after-N-seconds` | Keep the retry model for **N** seconds, then reset |
|
|
769
822
|
|
|
770
|
-
|
|
823
|
+
##### Reset after each request (default)
|
|
771
824
|
|
|
772
825
|
```typescript
|
|
773
826
|
const retryableModel = createRetryable({
|
|
774
827
|
model: openai('gpt-4o-mini'),
|
|
775
828
|
retries: [anthropic('claude-sonnet-4-20250514')],
|
|
776
|
-
reset: 'after-request', // default
|
|
829
|
+
reset: 'after-request', // default: always start with the base model
|
|
777
830
|
});
|
|
778
831
|
```
|
|
779
832
|
|
|
780
|
-
|
|
833
|
+
##### Keep the retry model for N requests
|
|
781
834
|
|
|
782
835
|
```typescript
|
|
783
836
|
const retryableModel = createRetryable({
|
|
@@ -787,7 +840,7 @@ const retryableModel = createRetryable({
|
|
|
787
840
|
});
|
|
788
841
|
```
|
|
789
842
|
|
|
790
|
-
|
|
843
|
+
##### Keep the retry model for N seconds
|
|
791
844
|
|
|
792
845
|
```typescript
|
|
793
846
|
const retryableModel = createRetryable({
|
|
@@ -808,12 +861,12 @@ In the second case, errors during stream processing will not always be retried,
|
|
|
808
861
|
|
|
809
862
|
### API Reference
|
|
810
863
|
|
|
811
|
-
#### `createRetryable(options: RetryableModelOptions):
|
|
864
|
+
#### `createRetryable(options: RetryableModelOptions): LanguageModelV3 | EmbeddingModelV3 | ImageModelV3`
|
|
812
865
|
|
|
813
|
-
Creates a retryable model that works with
|
|
866
|
+
Creates a retryable model that works with language models, embedding models, and image models.
|
|
814
867
|
|
|
815
868
|
```ts
|
|
816
|
-
interface RetryableModelOptions<MODEL extends
|
|
869
|
+
interface RetryableModelOptions<MODEL extends LanguageModelV3 | EmbeddingModelV3 | ImageModelV3> {
|
|
817
870
|
model: MODEL;
|
|
818
871
|
retries: Array<Retryable<MODEL> | MODEL>;
|
|
819
872
|
disabled?: boolean | (() => boolean);
|
|
@@ -827,7 +880,7 @@ interface RetryableModelOptions<MODEL extends LanguageModelV2 | EmbeddingModelV2
|
|
|
827
880
|
- `model`: The base model to use for the initial request.
|
|
828
881
|
- `retries`: Array of retryables (functions, models, or retry objects) to attempt on failure.
|
|
829
882
|
- `disabled`: Disable all retry logic. Can be a boolean or function returning boolean. Default: `false` (retries enabled).
|
|
830
|
-
- `reset`: Controls when to reset back to the base model after a successful retry.
|
|
883
|
+
- `reset`: Controls when to reset back to the base model after a successful retry. Default: `after-request`.
|
|
831
884
|
- `onError`: Callback invoked when an error occurs.
|
|
832
885
|
- `onRetry`: Callback invoked before attempting a retry.
|
|
833
886
|
|
|
@@ -842,9 +895,9 @@ type Reset =
|
|
|
842
895
|
| `after-${number}-seconds`;
|
|
843
896
|
```
|
|
844
897
|
|
|
845
|
-
- `
|
|
846
|
-
-
|
|
847
|
-
-
|
|
898
|
+
- `after-request` — reset immediately after the next request (default).
|
|
899
|
+
- `after-N-requests` — keep the retry model for the next N requests, then reset.
|
|
900
|
+
- `after-N-seconds` — keep the retry model for N seconds, then reset.
|
|
848
901
|
|
|
849
902
|
#### `Retryable`
|
|
850
903
|
|
|
@@ -859,17 +912,17 @@ type Retryable = (
|
|
|
859
912
|
|
|
860
913
|
#### `Retry`
|
|
861
914
|
|
|
862
|
-
A `Retry` specifies the model to retry and optional settings. The available options depend on the model type (language model or
|
|
915
|
+
A `Retry` specifies the model to retry and optional settings. The available options depend on the model type (language model, embedding model, or image model).
|
|
863
916
|
|
|
864
917
|
```typescript
|
|
865
918
|
interface Retry {
|
|
866
|
-
model:
|
|
919
|
+
model: LanguageModelV3 | EmbeddingModelV3 | ImageModelV3;
|
|
867
920
|
maxAttempts?: number; // Maximum retry attempts per model (default: 1)
|
|
868
921
|
delay?: number; // Delay in milliseconds before retrying
|
|
869
922
|
backoffFactor?: number; // Multiplier for exponential backoff
|
|
870
923
|
timeout?: number; // Timeout in milliseconds for the retry attempt
|
|
871
924
|
providerOptions?: ProviderOptions; // @deprecated - use options.providerOptions instead
|
|
872
|
-
options?:
|
|
925
|
+
options?: LanguageModelV3CallOptions | EmbeddingModelV3CallOptions | ImageModelV3CallOptions; // Call options to override for this retry
|
|
873
926
|
}
|
|
874
927
|
```
|
|
875
928
|
|
|
@@ -889,22 +942,22 @@ interface RetryContext {
|
|
|
889
942
|
A `RetryAttempt` represents a single attempt with a specific model, which can be either an error or a successful result that triggered a retry. Each attempt includes the call options that were used for that specific attempt. For retry attempts, this will reflect any overridden options from the retry configuration.
|
|
890
943
|
|
|
891
944
|
```typescript
|
|
892
|
-
// For
|
|
945
|
+
// For language, embedding, and image models
|
|
893
946
|
type RetryAttempt =
|
|
894
|
-
| {
|
|
895
|
-
type: 'error';
|
|
896
|
-
error: unknown;
|
|
897
|
-
model:
|
|
898
|
-
options:
|
|
947
|
+
| {
|
|
948
|
+
type: 'error';
|
|
949
|
+
error: unknown;
|
|
950
|
+
model: LanguageModelV3 | EmbeddingModelV3 | ImageModelV3;
|
|
951
|
+
options: LanguageModelV3CallOptions | EmbeddingModelV3CallOptions | ImageModelV3CallOptions;
|
|
899
952
|
}
|
|
900
|
-
| {
|
|
901
|
-
type: 'result';
|
|
902
|
-
result:
|
|
903
|
-
model:
|
|
904
|
-
options:
|
|
953
|
+
| {
|
|
954
|
+
type: 'result';
|
|
955
|
+
result: LanguageModelV3Generate;
|
|
956
|
+
model: LanguageModelV3;
|
|
957
|
+
options: LanguageModelV3CallOptions;
|
|
905
958
|
};
|
|
906
959
|
|
|
907
|
-
// Note: Result-based retries only apply to language models, not embedding models
|
|
960
|
+
// Note: Result-based retries only apply to language models, not embedding or image models
|
|
908
961
|
|
|
909
962
|
// Type guards for discriminating attempts
|
|
910
963
|
function isErrorAttempt(attempt: RetryAttempt): attempt is RetryErrorAttempt;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Retryable,
|
|
1
|
+
import { C as RetryAttempt, D as Retryable, E as RetryResultAttempt, O as RetryableModelOptions, S as Retry, T as RetryErrorAttempt, _ as Reset, a as GatewayLanguageModelId, b as ResolvedModel, c as ImageModelGenerate, d as LanguageModelCallOptions, f as LanguageModelGenerate, g as ProviderOptions, h as LanguageModelStreamPart, i as EmbeddingModelRetryCallOptions, k as RetryableOptions, l as ImageModelRetryCallOptions, m as LanguageModelStream, n as EmbeddingModelCallOptions, o as ImageModel, p as LanguageModelRetryCallOptions, r as EmbeddingModelEmbed, s as ImageModelCallOptions, t as EmbeddingModel, u as LanguageModel, v as ResolvableLanguageModel, w as RetryContext, x as Retries, y as ResolvableModel } from "./types-wEZKtEcH.mjs";
|
|
2
2
|
import * as _ai_sdk_provider0 from "@ai-sdk/provider";
|
|
3
3
|
|
|
4
4
|
//#region src/create-retryable-model.d.ts
|
|
@@ -7,19 +7,21 @@ declare function createRetryable<MODEL extends LanguageModel>(options: Omit<Retr
|
|
|
7
7
|
}): LanguageModel;
|
|
8
8
|
declare function createRetryable<MODEL extends LanguageModel>(options: RetryableModelOptions<MODEL>): LanguageModel;
|
|
9
9
|
declare function createRetryable<MODEL extends EmbeddingModel>(options: RetryableModelOptions<MODEL>): EmbeddingModel;
|
|
10
|
+
declare function createRetryable<MODEL extends ImageModel>(options: RetryableModelOptions<MODEL>): ImageModel;
|
|
10
11
|
//#endregion
|
|
11
12
|
//#region src/get-model-key.d.ts
|
|
12
13
|
/**
|
|
13
|
-
* Generate a unique key for a
|
|
14
|
+
* Generate a unique key for a model instance.
|
|
14
15
|
*/
|
|
15
|
-
declare const getModelKey: (model: LanguageModel | EmbeddingModel) => string;
|
|
16
|
+
declare const getModelKey: (model: LanguageModel | EmbeddingModel | ImageModel) => string;
|
|
16
17
|
//#endregion
|
|
17
18
|
//#region src/utils.d.ts
|
|
18
19
|
declare const isObject: (value: unknown) => value is Record<string, unknown>;
|
|
19
20
|
declare const isString: (value: unknown) => value is string;
|
|
20
|
-
declare const isModel: (model: unknown) => model is LanguageModel | EmbeddingModel;
|
|
21
|
+
declare const isModel: (model: unknown) => model is LanguageModel | EmbeddingModel | ImageModel;
|
|
21
22
|
declare const isLanguageModel: (model: unknown) => model is LanguageModel;
|
|
22
23
|
declare const isEmbeddingModel: (model: unknown) => model is EmbeddingModel;
|
|
24
|
+
declare const isImageModel: (model: unknown) => model is ImageModel;
|
|
23
25
|
declare const isStreamResult: (result: LanguageModelGenerate | LanguageModelStream) => result is LanguageModelStream;
|
|
24
26
|
declare const isGenerateResult: (result: LanguageModelGenerate | LanguageModelStream) => result is LanguageModelGenerate;
|
|
25
27
|
/**
|
|
@@ -73,4 +75,4 @@ declare const isAbortError: (error: unknown) => boolean;
|
|
|
73
75
|
*/
|
|
74
76
|
declare const isTimeoutError: (error: unknown) => boolean;
|
|
75
77
|
//#endregion
|
|
76
|
-
export { EmbeddingModel, EmbeddingModelCallOptions, EmbeddingModelEmbed, EmbeddingModelRetryCallOptions, GatewayLanguageModelId, LanguageModel, LanguageModelCallOptions, LanguageModelGenerate, LanguageModelRetryCallOptions, LanguageModelStream, LanguageModelStreamPart, ProviderOptions, Reset, ResolvableLanguageModel, ResolvableModel, ResolvedModel, Retries, Retry, RetryAttempt, RetryContext, RetryErrorAttempt, RetryResultAttempt, Retryable, RetryableModelOptions, RetryableOptions, createRetryable, getModelKey, isAbortError, isEmbeddingModel, isErrorAttempt, isGenerateResult, isLanguageModel, isModel, isObject, isResultAttempt, isStreamContentPart, isStreamResult, isString, isTimeoutError };
|
|
78
|
+
export { EmbeddingModel, EmbeddingModelCallOptions, EmbeddingModelEmbed, EmbeddingModelRetryCallOptions, GatewayLanguageModelId, ImageModel, ImageModelCallOptions, ImageModelGenerate, ImageModelRetryCallOptions, LanguageModel, LanguageModelCallOptions, LanguageModelGenerate, LanguageModelRetryCallOptions, LanguageModelStream, LanguageModelStreamPart, ProviderOptions, Reset, ResolvableLanguageModel, ResolvableModel, ResolvedModel, Retries, Retry, RetryAttempt, RetryContext, RetryErrorAttempt, RetryResultAttempt, Retryable, RetryableModelOptions, RetryableOptions, createRetryable, getModelKey, isAbortError, isEmbeddingModel, isErrorAttempt, isGenerateResult, isImageModel, isLanguageModel, isModel, isObject, isResultAttempt, isStreamContentPart, isStreamResult, isString, isTimeoutError };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as isImageModel, c as isObject, d as isStreamResult, f as isString, i as isGenerateResult, l as isResultAttempt, n as isEmbeddingModel, o as isLanguageModel, p as isTimeoutError, r as isErrorAttempt, s as isModel, t as isAbortError, u as isStreamContentPart } from "./utils-CfnsSGrw.mjs";
|
|
2
2
|
import { RetryError, gateway } from "ai";
|
|
3
3
|
import { delay } from "@ai-sdk/provider-utils";
|
|
4
4
|
import { getErrorMessage } from "@ai-sdk/provider";
|
|
@@ -94,7 +94,7 @@ function calculateExponentialBackoff(baseDelay, backoffFactor = 1, attempts) {
|
|
|
94
94
|
//#endregion
|
|
95
95
|
//#region src/get-model-key.ts
|
|
96
96
|
/**
|
|
97
|
-
* Generate a unique key for a
|
|
97
|
+
* Generate a unique key for a model instance.
|
|
98
98
|
*/
|
|
99
99
|
const getModelKey = (model) => {
|
|
100
100
|
return `${model.provider}/${model.modelId}`;
|
|
@@ -110,7 +110,7 @@ function countModelAttempts(model, attempts) {
|
|
|
110
110
|
//#endregion
|
|
111
111
|
//#region src/resolve-model.ts
|
|
112
112
|
/**
|
|
113
|
-
* Resolve a model string via the AI SDK Gateway to a
|
|
113
|
+
* Resolve a model string via the AI SDK Gateway to a model instance
|
|
114
114
|
*/
|
|
115
115
|
function resolveModel(model) {
|
|
116
116
|
return isModel(model) ? model : gateway(model);
|
|
@@ -133,9 +133,20 @@ async function findRetryModel(retries, context) {
|
|
|
133
133
|
*/
|
|
134
134
|
for (const retry of applicableRetries) {
|
|
135
135
|
let retryModel;
|
|
136
|
-
if (typeof retry ===
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
if (typeof retry === `function`)
|
|
137
|
+
/**
|
|
138
|
+
* Function retryable - call it with context
|
|
139
|
+
* The function can be either Retryable<MODEL> or Retryable<ResolvableLanguageModel>
|
|
140
|
+
* At runtime, both work because the context is structurally compatible
|
|
141
|
+
* We use type assertion here because TypeScript can't prove the union type compatibility
|
|
142
|
+
*/
|
|
143
|
+
retryModel = await retry(context);
|
|
144
|
+
else if (isObject(retry) && `model` in retry)
|
|
145
|
+
/** Static Retry object */
|
|
146
|
+
retryModel = retry;
|
|
147
|
+
else
|
|
148
|
+
/** Plain model */
|
|
149
|
+
retryModel = { model: retry };
|
|
139
150
|
if (retryModel) {
|
|
140
151
|
/**
|
|
141
152
|
* The model can be string or an instance.
|
|
@@ -322,6 +333,152 @@ var RetryableEmbeddingModel = class extends BaseRetryableModel {
|
|
|
322
333
|
}
|
|
323
334
|
};
|
|
324
335
|
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/retryable-image-model.ts
|
|
338
|
+
var RetryableImageModel = class extends BaseRetryableModel {
|
|
339
|
+
specificationVersion = "v3";
|
|
340
|
+
get modelId() {
|
|
341
|
+
return this.currentModel.modelId;
|
|
342
|
+
}
|
|
343
|
+
get provider() {
|
|
344
|
+
return this.currentModel.provider;
|
|
345
|
+
}
|
|
346
|
+
get maxImagesPerCall() {
|
|
347
|
+
return this.currentModel.maxImagesPerCall;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Get the retry call options overrides from a retry configuration.
|
|
351
|
+
*/
|
|
352
|
+
getRetryCallOptions(callOptions, currentRetry) {
|
|
353
|
+
const retryOptions = currentRetry?.options ?? {};
|
|
354
|
+
return {
|
|
355
|
+
...callOptions,
|
|
356
|
+
n: retryOptions.n ?? callOptions.n,
|
|
357
|
+
size: retryOptions.size ?? callOptions.size,
|
|
358
|
+
aspectRatio: retryOptions.aspectRatio ?? callOptions.aspectRatio,
|
|
359
|
+
seed: retryOptions.seed ?? callOptions.seed,
|
|
360
|
+
headers: retryOptions.headers ?? callOptions.headers,
|
|
361
|
+
providerOptions: retryOptions.providerOptions ?? currentRetry?.providerOptions ?? callOptions.providerOptions,
|
|
362
|
+
abortSignal: currentRetry?.timeout ? AbortSignal.timeout(currentRetry.timeout) : callOptions.abortSignal
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Execute a function with retry logic for handling errors
|
|
367
|
+
*/
|
|
368
|
+
async withRetry(input) {
|
|
369
|
+
/**
|
|
370
|
+
* Track all attempts.
|
|
371
|
+
*/
|
|
372
|
+
const attempts = input.attempts ?? [];
|
|
373
|
+
/**
|
|
374
|
+
* Track current retry configuration.
|
|
375
|
+
*/
|
|
376
|
+
let currentRetry;
|
|
377
|
+
while (true) {
|
|
378
|
+
/**
|
|
379
|
+
* The previous attempt that triggered a retry, or undefined if this is the first attempt
|
|
380
|
+
*/
|
|
381
|
+
const previousAttempt = attempts.at(-1);
|
|
382
|
+
/**
|
|
383
|
+
* Call the onRetry handler if provided.
|
|
384
|
+
* Skip on the first attempt since no previous attempt exists yet.
|
|
385
|
+
*/
|
|
386
|
+
if (previousAttempt) {
|
|
387
|
+
const context = {
|
|
388
|
+
current: {
|
|
389
|
+
...previousAttempt,
|
|
390
|
+
model: this.currentModel
|
|
391
|
+
},
|
|
392
|
+
attempts: [...attempts]
|
|
393
|
+
};
|
|
394
|
+
this.options.onRetry?.(context);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Get the retry call options overrides for this attempt
|
|
398
|
+
*/
|
|
399
|
+
const retryCallOptions = this.getRetryCallOptions(input.callOptions, currentRetry);
|
|
400
|
+
try {
|
|
401
|
+
return {
|
|
402
|
+
result: await input.fn(retryCallOptions),
|
|
403
|
+
attempts
|
|
404
|
+
};
|
|
405
|
+
} catch (error) {
|
|
406
|
+
/** Don't retry if user manually aborted the request. */
|
|
407
|
+
/** TimeoutError from AbortSignal.timeout() will still be handled by retry handlers. */
|
|
408
|
+
if (isAbortError(error)) throw error;
|
|
409
|
+
const { retryModel, attempt } = await this.handleError(error, attempts, retryCallOptions);
|
|
410
|
+
attempts.push(attempt);
|
|
411
|
+
if (retryModel.delay) {
|
|
412
|
+
/**
|
|
413
|
+
* Calculate exponential backoff delay based on the number of attempts for this specific model.
|
|
414
|
+
* The delay grows exponentially: baseDelay * backoffFactor^attempts
|
|
415
|
+
* Example: With delay=1000ms and backoffFactor=2:
|
|
416
|
+
* - Attempt 1: 1000ms
|
|
417
|
+
* - Attempt 2: 2000ms
|
|
418
|
+
* - Attempt 3: 4000ms
|
|
419
|
+
*/
|
|
420
|
+
const modelAttemptsCount = countModelAttempts(retryModel.model, attempts);
|
|
421
|
+
await delay(calculateExponentialBackoff(retryModel.delay, retryModel.backoffFactor, modelAttemptsCount), { abortSignal: retryCallOptions.abortSignal });
|
|
422
|
+
}
|
|
423
|
+
this.currentModel = retryModel.model;
|
|
424
|
+
currentRetry = retryModel;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Handle an error and determine if a retry is needed
|
|
430
|
+
*/
|
|
431
|
+
async handleError(error, attempts, callOptions) {
|
|
432
|
+
const errorAttempt = {
|
|
433
|
+
type: "error",
|
|
434
|
+
error,
|
|
435
|
+
model: this.currentModel,
|
|
436
|
+
options: callOptions
|
|
437
|
+
};
|
|
438
|
+
/**
|
|
439
|
+
* Save the current attempt
|
|
440
|
+
*/
|
|
441
|
+
const updatedAttempts = [...attempts, errorAttempt];
|
|
442
|
+
const context = {
|
|
443
|
+
current: errorAttempt,
|
|
444
|
+
attempts: updatedAttempts
|
|
445
|
+
};
|
|
446
|
+
this.options.onError?.(context);
|
|
447
|
+
const retryModel = await findRetryModel(this.options.retries, context);
|
|
448
|
+
/**
|
|
449
|
+
* Handler didn't return any models to try next, rethrow the error.
|
|
450
|
+
* If we retried the request, wrap the error into a `RetryError` for better visibility.
|
|
451
|
+
*/
|
|
452
|
+
if (!retryModel) {
|
|
453
|
+
if (updatedAttempts.length > 1) throw prepareRetryError(error, updatedAttempts);
|
|
454
|
+
throw error;
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
retryModel,
|
|
458
|
+
attempt: errorAttempt
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
async doGenerate(callOptions) {
|
|
462
|
+
/**
|
|
463
|
+
* Resolve the starting model (base or sticky)
|
|
464
|
+
*/
|
|
465
|
+
const startModel = this.resolveStartModel();
|
|
466
|
+
this.currentModel = startModel;
|
|
467
|
+
/**
|
|
468
|
+
* If retries are disabled, bypass retry machinery entirely
|
|
469
|
+
*/
|
|
470
|
+
if (this.isDisabled()) return this.currentModel.doGenerate(callOptions);
|
|
471
|
+
const { result } = await this.withRetry({
|
|
472
|
+
fn: async (retryCallOptions) => {
|
|
473
|
+
return this.currentModel.doGenerate(retryCallOptions);
|
|
474
|
+
},
|
|
475
|
+
callOptions
|
|
476
|
+
});
|
|
477
|
+
this.updateStickyModel(startModel);
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
|
|
325
482
|
//#endregion
|
|
326
483
|
//#region src/retryable-language-model.ts
|
|
327
484
|
var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
@@ -630,6 +787,10 @@ function createRetryable(options) {
|
|
|
630
787
|
...options,
|
|
631
788
|
model
|
|
632
789
|
});
|
|
790
|
+
if (isImageModel(model)) return new RetryableImageModel({
|
|
791
|
+
...options,
|
|
792
|
+
model
|
|
793
|
+
});
|
|
633
794
|
return new RetryableLanguageModel({
|
|
634
795
|
...options,
|
|
635
796
|
model
|
|
@@ -637,4 +798,4 @@ function createRetryable(options) {
|
|
|
637
798
|
}
|
|
638
799
|
|
|
639
800
|
//#endregion
|
|
640
|
-
export { createRetryable, getModelKey, isAbortError, isEmbeddingModel, isErrorAttempt, isGenerateResult, isLanguageModel, isModel, isObject, isResultAttempt, isStreamContentPart, isStreamResult, isString, isTimeoutError };
|
|
801
|
+
export { createRetryable, getModelKey, isAbortError, isEmbeddingModel, isErrorAttempt, isGenerateResult, isImageModel, isLanguageModel, isModel, isObject, isResultAttempt, isStreamContentPart, isStreamResult, isString, isTimeoutError };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as Retryable, k as RetryableOptions, o as ImageModel, t as EmbeddingModel, v as ResolvableLanguageModel } from "../types-wEZKtEcH.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/retryables/content-filter-triggered.d.ts
|
|
4
4
|
/**
|
|
@@ -6,11 +6,17 @@ import { C as Retryable, T as RetryableOptions, m as ResolvableLanguageModel, t
|
|
|
6
6
|
*/
|
|
7
7
|
declare function contentFilterTriggered<MODEL extends ResolvableLanguageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
8
8
|
//#endregion
|
|
9
|
+
//#region src/retryables/no-image-generated.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* Fallback to a different model if image generation fails with NoImageGeneratedError.
|
|
12
|
+
*/
|
|
13
|
+
declare function noImageGenerated<MODEL extends ImageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
14
|
+
//#endregion
|
|
9
15
|
//#region src/retryables/request-not-retryable.d.ts
|
|
10
16
|
/**
|
|
11
17
|
* Fallback to a different model if the error is non-retryable.
|
|
12
18
|
*/
|
|
13
|
-
declare function requestNotRetryable<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
19
|
+
declare function requestNotRetryable<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
14
20
|
//#endregion
|
|
15
21
|
//#region src/retryables/request-timeout.d.ts
|
|
16
22
|
/**
|
|
@@ -18,7 +24,7 @@ declare function requestNotRetryable<MODEL extends ResolvableLanguageModel | Emb
|
|
|
18
24
|
* Use in combination with the `abortSignal` option.
|
|
19
25
|
* If no timeout is specified, a default of 60 seconds is used.
|
|
20
26
|
*/
|
|
21
|
-
declare function requestTimeout<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
27
|
+
declare function requestTimeout<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
22
28
|
//#endregion
|
|
23
29
|
//#region src/retryables/retry-after-delay.d.ts
|
|
24
30
|
/**
|
|
@@ -26,7 +32,7 @@ declare function requestTimeout<MODEL extends ResolvableLanguageModel | Embeddin
|
|
|
26
32
|
* Uses the `Retry-After` or `Retry-After-Ms` headers if present.
|
|
27
33
|
* Otherwise uses the specified `delay` and `backoffFactor` if provided.
|
|
28
34
|
*/
|
|
29
|
-
declare function retryAfterDelay<MODEL extends ResolvableLanguageModel | EmbeddingModel>(options: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
35
|
+
declare function retryAfterDelay<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel>(options: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
30
36
|
//#endregion
|
|
31
37
|
//#region src/retryables/schema-mismatch.d.ts
|
|
32
38
|
/**
|
|
@@ -58,13 +64,13 @@ declare function schemaMismatch<MODEL extends ResolvableLanguageModel>(model: MO
|
|
|
58
64
|
* - Response with `type: "overloaded_error"`
|
|
59
65
|
* - Response with a `message` containing "overloaded"
|
|
60
66
|
*/
|
|
61
|
-
declare function serviceOverloaded<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
67
|
+
declare function serviceOverloaded<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
62
68
|
//#endregion
|
|
63
69
|
//#region src/retryables/service-unavailable.d.ts
|
|
64
70
|
/**
|
|
65
71
|
* Fallback to a different model if the provider returns a service unavailable error.
|
|
66
72
|
* This retryable handles HTTP status code 503 (Service Unavailable).
|
|
67
73
|
*/
|
|
68
|
-
declare function serviceUnavailable<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
74
|
+
declare function serviceUnavailable<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
69
75
|
//#endregion
|
|
70
|
-
export { contentFilterTriggered, requestNotRetryable, requestTimeout, retryAfterDelay, schemaMismatch, serviceOverloaded, serviceUnavailable };
|
|
76
|
+
export { contentFilterTriggered, noImageGenerated, requestNotRetryable, requestTimeout, retryAfterDelay, schemaMismatch, serviceOverloaded, serviceUnavailable };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as
|
|
2
|
-
import { APICallError } from "ai";
|
|
1
|
+
import { c as isObject, f as isString, l as isResultAttempt, p as isTimeoutError, r as isErrorAttempt } from "../utils-CfnsSGrw.mjs";
|
|
2
|
+
import { APICallError, NoImageGeneratedError } from "ai";
|
|
3
3
|
import { safeParseJSON } from "@ai-sdk/provider-utils";
|
|
4
4
|
import { fromJSONSchema } from "zod";
|
|
5
5
|
|
|
@@ -29,6 +29,25 @@ function contentFilterTriggered(model, options) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/retryables/no-image-generated.ts
|
|
34
|
+
/**
|
|
35
|
+
* Fallback to a different model if image generation fails with NoImageGeneratedError.
|
|
36
|
+
*/
|
|
37
|
+
function noImageGenerated(model, options) {
|
|
38
|
+
return (context) => {
|
|
39
|
+
const { current } = context;
|
|
40
|
+
if (isErrorAttempt(current)) {
|
|
41
|
+
const { error } = current;
|
|
42
|
+
if (NoImageGeneratedError.isInstance(error)) return {
|
|
43
|
+
model,
|
|
44
|
+
maxAttempts: 1,
|
|
45
|
+
...options
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
32
51
|
//#endregion
|
|
33
52
|
//#region src/retryables/request-not-retryable.ts
|
|
34
53
|
/**
|
|
@@ -219,4 +238,4 @@ function serviceUnavailable(model, options) {
|
|
|
219
238
|
}
|
|
220
239
|
|
|
221
240
|
//#endregion
|
|
222
|
-
export { contentFilterTriggered, requestNotRetryable, requestTimeout, retryAfterDelay, schemaMismatch, serviceOverloaded, serviceUnavailable };
|
|
241
|
+
export { contentFilterTriggered, noImageGenerated, requestNotRetryable, requestTimeout, retryAfterDelay, schemaMismatch, serviceOverloaded, serviceUnavailable };
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { gateway } from "ai";
|
|
2
|
-
import { EmbeddingModelV3, LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3StreamPart, SharedV3ProviderOptions } from "@ai-sdk/provider";
|
|
2
|
+
import { EmbeddingModelV3, ImageModelV3, ImageModelV3CallOptions, LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3StreamPart, SharedV3ProviderOptions } from "@ai-sdk/provider";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
5
|
type Literals<T> = T extends string ? string extends T ? never : T : never;
|
|
6
6
|
type LanguageModel = LanguageModelV3;
|
|
7
7
|
type EmbeddingModel = EmbeddingModelV3;
|
|
8
|
+
type ImageModel = ImageModelV3;
|
|
8
9
|
type LanguageModelCallOptions = LanguageModelV3CallOptions;
|
|
9
10
|
type LanguageModelStreamPart = LanguageModelV3StreamPart;
|
|
11
|
+
type ImageModelCallOptions = ImageModelV3CallOptions;
|
|
10
12
|
type ProviderOptions = SharedV3ProviderOptions;
|
|
11
13
|
type GatewayLanguageModelId = Parameters<(typeof gateway)['languageModel']>[0];
|
|
12
14
|
type ResolvableLanguageModel = LanguageModel | Literals<GatewayLanguageModelId>;
|
|
13
|
-
type ResolvableModel<MODEL extends LanguageModel | EmbeddingModel> = MODEL extends LanguageModel ? ResolvableLanguageModel : EmbeddingModel;
|
|
14
|
-
type ResolvedModel<MODEL extends ResolvableLanguageModel | EmbeddingModel> = MODEL extends ResolvableLanguageModel ? LanguageModel : EmbeddingModel;
|
|
15
|
+
type ResolvableModel<MODEL extends LanguageModel | EmbeddingModel | ImageModel> = MODEL extends LanguageModel ? ResolvableLanguageModel : MODEL extends EmbeddingModel ? EmbeddingModel : ImageModel;
|
|
16
|
+
type ResolvedModel<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel> = MODEL extends ResolvableLanguageModel ? LanguageModel : MODEL extends EmbeddingModel ? EmbeddingModel : ImageModel;
|
|
15
17
|
/**
|
|
16
18
|
* Call options that can be overridden during retry for language models.
|
|
17
19
|
*/
|
|
@@ -20,10 +22,14 @@ type LanguageModelRetryCallOptions = Partial<Pick<LanguageModelCallOptions, 'pro
|
|
|
20
22
|
* Call options that can be overridden during retry for embedding models.
|
|
21
23
|
*/
|
|
22
24
|
type EmbeddingModelRetryCallOptions = Partial<Pick<EmbeddingModelCallOptions, 'values' | 'headers' | 'providerOptions'>>;
|
|
25
|
+
/**
|
|
26
|
+
* Call options that can be overridden during retry for image models.
|
|
27
|
+
*/
|
|
28
|
+
type ImageModelRetryCallOptions = Partial<Pick<ImageModelCallOptions, 'n' | 'size' | 'aspectRatio' | 'seed' | 'headers' | 'providerOptions'>>;
|
|
23
29
|
/**
|
|
24
30
|
* A retry attempt with an error
|
|
25
31
|
*/
|
|
26
|
-
type RetryErrorAttempt<MODEL extends LanguageModel | EmbeddingModel> = {
|
|
32
|
+
type RetryErrorAttempt<MODEL extends LanguageModel | EmbeddingModel | ImageModel> = {
|
|
27
33
|
type: 'error';
|
|
28
34
|
error: unknown;
|
|
29
35
|
result?: undefined;
|
|
@@ -31,7 +37,7 @@ type RetryErrorAttempt<MODEL extends LanguageModel | EmbeddingModel> = {
|
|
|
31
37
|
/**
|
|
32
38
|
* The call options used for this attempt.
|
|
33
39
|
*/
|
|
34
|
-
options: MODEL extends LanguageModel ? LanguageModelCallOptions : EmbeddingModelCallOptions;
|
|
40
|
+
options: MODEL extends LanguageModel ? LanguageModelCallOptions : MODEL extends EmbeddingModel ? EmbeddingModelCallOptions : ImageModelCallOptions;
|
|
35
41
|
};
|
|
36
42
|
/**
|
|
37
43
|
* A retry attempt with a successful result
|
|
@@ -49,11 +55,11 @@ type RetryResultAttempt = {
|
|
|
49
55
|
/**
|
|
50
56
|
* A retry attempt with either an error or a result and the model used
|
|
51
57
|
*/
|
|
52
|
-
type RetryAttempt<MODEL extends LanguageModel | EmbeddingModel> = RetryErrorAttempt<MODEL> | RetryResultAttempt
|
|
58
|
+
type RetryAttempt<MODEL extends LanguageModel | EmbeddingModel | ImageModel> = MODEL extends LanguageModel ? RetryErrorAttempt<MODEL> | RetryResultAttempt : RetryErrorAttempt<MODEL>;
|
|
53
59
|
/**
|
|
54
60
|
* The context provided to Retryables with the current attempt and all previous attempts.
|
|
55
61
|
*/
|
|
56
|
-
type RetryContext<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
62
|
+
type RetryContext<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel> = {
|
|
57
63
|
/**
|
|
58
64
|
* Current attempt that caused the retry
|
|
59
65
|
*/
|
|
@@ -66,7 +72,7 @@ type RetryContext<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
|
66
72
|
/**
|
|
67
73
|
* Options for creating a retryable model.
|
|
68
74
|
*/
|
|
69
|
-
interface RetryableModelOptions<MODEL extends LanguageModel | EmbeddingModel> {
|
|
75
|
+
interface RetryableModelOptions<MODEL extends LanguageModel | EmbeddingModel | ImageModel> {
|
|
70
76
|
model: MODEL;
|
|
71
77
|
retries: Retries<MODEL>;
|
|
72
78
|
disabled?: boolean | (() => boolean);
|
|
@@ -90,7 +96,7 @@ interface RetryableModelOptions<MODEL extends LanguageModel | EmbeddingModel> {
|
|
|
90
96
|
* This flexible approach allows retryable functions to return the exact model type
|
|
91
97
|
* they received without type assertions, while still supporting string-based gateway models.
|
|
92
98
|
*/
|
|
93
|
-
type Retry<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
99
|
+
type Retry<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel> = {
|
|
94
100
|
model: MODEL;
|
|
95
101
|
/**
|
|
96
102
|
* Maximum number of attempts for this model.
|
|
@@ -112,7 +118,7 @@ type Retry<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
|
112
118
|
/**
|
|
113
119
|
* Call options to override for this retry.
|
|
114
120
|
*/
|
|
115
|
-
options?: MODEL extends LanguageModel ? Partial<LanguageModelRetryCallOptions> : Partial<EmbeddingModelRetryCallOptions>;
|
|
121
|
+
options?: MODEL extends LanguageModel ? Partial<LanguageModelRetryCallOptions> : MODEL extends EmbeddingModel ? Partial<EmbeddingModelRetryCallOptions> : Partial<ImageModelRetryCallOptions>;
|
|
116
122
|
/**
|
|
117
123
|
* @deprecated Use `options.providerOptions` instead.
|
|
118
124
|
* Provider options to override for this retry.
|
|
@@ -124,9 +130,9 @@ type Retry<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
|
124
130
|
/**
|
|
125
131
|
* A function that determines whether to retry with a different model based on the current attempt and all previous attempts.
|
|
126
132
|
*/
|
|
127
|
-
type Retryable<MODEL extends ResolvableLanguageModel | EmbeddingModel> = (context: RetryContext<MODEL>) => Retry<MODEL> | Promise<Retry<MODEL> | undefined> | undefined;
|
|
128
|
-
type Retries<MODEL extends LanguageModel | EmbeddingModel> = Array<Retryable<ResolvableModel<MODEL>> | Retry<ResolvableModel<MODEL>> | ResolvableModel<MODEL>>;
|
|
129
|
-
type RetryableOptions<MODEL extends ResolvableLanguageModel | EmbeddingModel> = Partial<Omit<Retry<MODEL>, 'model'>>;
|
|
133
|
+
type Retryable<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel> = (context: RetryContext<MODEL>) => Retry<MODEL> | Promise<Retry<MODEL> | undefined> | undefined;
|
|
134
|
+
type Retries<MODEL extends LanguageModel | EmbeddingModel | ImageModel> = Array<Retryable<ResolvableModel<MODEL>> | Retry<ResolvableModel<MODEL>> | ResolvableModel<MODEL>>;
|
|
135
|
+
type RetryableOptions<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel> = Partial<Omit<Retry<MODEL>, 'model'>>;
|
|
130
136
|
/**
|
|
131
137
|
* Controls when to reset the sticky model back to the base model.
|
|
132
138
|
*
|
|
@@ -139,5 +145,6 @@ type LanguageModelGenerate = Awaited<ReturnType<LanguageModel['doGenerate']>>;
|
|
|
139
145
|
type LanguageModelStream = Awaited<ReturnType<LanguageModel['doStream']>>;
|
|
140
146
|
type EmbeddingModelCallOptions = Parameters<EmbeddingModel['doEmbed']>[0];
|
|
141
147
|
type EmbeddingModelEmbed = Awaited<ReturnType<EmbeddingModel['doEmbed']>>;
|
|
148
|
+
type ImageModelGenerate = Awaited<ReturnType<ImageModel['doGenerate']>>;
|
|
142
149
|
//#endregion
|
|
143
|
-
export {
|
|
150
|
+
export { RetryAttempt as C, Retryable as D, RetryResultAttempt as E, RetryableModelOptions as O, Retry as S, RetryErrorAttempt as T, Reset as _, GatewayLanguageModelId as a, ResolvedModel as b, ImageModelGenerate as c, LanguageModelCallOptions as d, LanguageModelGenerate as f, ProviderOptions as g, LanguageModelStreamPart as h, EmbeddingModelRetryCallOptions as i, RetryableOptions as k, ImageModelRetryCallOptions as l, LanguageModelStream as m, EmbeddingModelCallOptions as n, ImageModel as o, LanguageModelRetryCallOptions as p, EmbeddingModelEmbed as r, ImageModelCallOptions as s, EmbeddingModel as t, LanguageModel as u, ResolvableLanguageModel as v, RetryContext as w, Retries as x, ResolvableModel as y };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
//#region src/utils.ts
|
|
2
2
|
const isObject = (value) => typeof value === "object" && value !== null;
|
|
3
3
|
const isString = (value) => typeof value === "string";
|
|
4
|
-
const isModel = (model) => isLanguageModel(model) || isEmbeddingModel(model);
|
|
5
|
-
const isLanguageModel = (model) => isObject(model) && "provider" in model && "modelId" in model && "specificationVersion" in model && "doGenerate" in model && model.specificationVersion === "v3";
|
|
4
|
+
const isModel = (model) => isLanguageModel(model) || isEmbeddingModel(model) || isImageModel(model);
|
|
5
|
+
const isLanguageModel = (model) => isObject(model) && "provider" in model && "modelId" in model && "specificationVersion" in model && "doGenerate" in model && "doStream" in model && model.specificationVersion === "v3";
|
|
6
6
|
const isEmbeddingModel = (model) => isObject(model) && "provider" in model && "modelId" in model && "specificationVersion" in model && "doEmbed" in model && model.specificationVersion === "v3";
|
|
7
|
+
const isImageModel = (model) => isObject(model) && "provider" in model && "modelId" in model && "specificationVersion" in model && "doGenerate" in model && model.specificationVersion === "v3" && !("doStream" in model) && !("doEmbed" in model);
|
|
7
8
|
const isStreamResult = (result) => "stream" in result;
|
|
8
9
|
const isGenerateResult = (result) => "content" in result;
|
|
9
10
|
/**
|
|
@@ -38,4 +39,4 @@ const isAbortError = (error) => error instanceof Error && error.name === "AbortE
|
|
|
38
39
|
const isTimeoutError = (error) => error instanceof Error && error.name === "TimeoutError";
|
|
39
40
|
|
|
40
41
|
//#endregion
|
|
41
|
-
export {
|
|
42
|
+
export { isImageModel as a, isObject as c, isStreamResult as d, isString as f, isGenerateResult as i, isResultAttempt as l, isEmbeddingModel as n, isLanguageModel as o, isTimeoutError as p, isErrorAttempt as r, isModel as s, isAbortError as t, isStreamContentPart as u };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-retry",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "AI SDK
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Retry and fallback mechanisms for AI SDK",
|
|
5
5
|
"types": "./dist/index.d.mts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@ai-sdk/anthropic": "3.0.23",
|
|
35
35
|
"@ai-sdk/azure": "3.0.19",
|
|
36
36
|
"@ai-sdk/gateway": "3.0.23",
|
|
37
|
+
"@ai-sdk/google": "^3.0.33",
|
|
37
38
|
"@ai-sdk/groq": "3.0.15",
|
|
38
39
|
"@ai-sdk/openai": "3.0.19",
|
|
39
40
|
"@ai-sdk/test-server": "1.0.3",
|