ai-retry 0.10.3 → 1.0.0-beta.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 +40 -2
- package/dist/index.d.mts +15 -22
- package/dist/index.mjs +35 -10
- package/dist/retryables/index.d.mts +7 -7
- package/dist/retryables/index.mjs +2 -2
- package/dist/types-D7G-2JLh.d.mts +90 -0
- package/dist/{utils-C26pNHta.mjs → utils-BXFlA2mh.mjs} +4 -8
- package/package.json +14 -12
- package/dist/types-TotEvw-5.d.mts +0 -76
package/README.md
CHANGED
|
@@ -19,13 +19,16 @@ It supports two types of retries:
|
|
|
19
19
|
|
|
20
20
|
### Installation
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Install the beta version of `ai-retry` to support AI SDK v6.
|
|
23
|
+
|
|
24
|
+
> [!NOTE]
|
|
25
|
+
> AI SDK v6 is still in beta, so break changes are expected.
|
|
23
26
|
|
|
24
27
|
> [!NOTE]
|
|
25
28
|
> AI SDK v6 support is available in the [v6 branch](https://github.com/zirkelc/ai-retry/tree/v6).
|
|
26
29
|
|
|
27
30
|
```bash
|
|
28
|
-
npm install ai-retry
|
|
31
|
+
npm install ai-retry@beta
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
### Usage
|
|
@@ -94,6 +97,41 @@ const result = await embed({
|
|
|
94
97
|
console.log(result.embedding);
|
|
95
98
|
```
|
|
96
99
|
|
|
100
|
+
#### Vercel AI Gateway
|
|
101
|
+
|
|
102
|
+
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.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { gateway } from 'ai';
|
|
106
|
+
import { createRetryable } from 'ai-retry';
|
|
107
|
+
|
|
108
|
+
const retryableModel = createRetryable({
|
|
109
|
+
model: 'openai/gpt-5',
|
|
110
|
+
retries: [
|
|
111
|
+
'anthropic/claude-sonnet-4'
|
|
112
|
+
]
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Is the same as:
|
|
116
|
+
const retryableModel = createRetryable({
|
|
117
|
+
model: gateway('openai/gpt-5'),
|
|
118
|
+
retries: [
|
|
119
|
+
gateway('anthropic/claude-sonnet-4')
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
By default, the `gateway` provider resolves model strings as language models. If you want to use an embedding model, you need to use the `textEmbeddingModel` method.
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { gateway } from 'ai';
|
|
128
|
+
import { createRetryable } from 'ai-retry';
|
|
129
|
+
|
|
130
|
+
const retryableModel = createRetryable({
|
|
131
|
+
model: gateway.textEmbeddingModel('openai/text-embedding-3-large'),
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
97
135
|
### Retryables
|
|
98
136
|
|
|
99
137
|
The objects passed to the `retries` are called retryables and control the retry behavior. We can distinguish between two types of retryables:
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as RetryableOptions, _ as RetryContext, a as LanguageModel, b as Retryable, c as LanguageModelStream, d as ResolvableLanguageModel, f as ResolvableModel, g as RetryAttempt, h as Retry, i as GatewayLanguageModelId, l as LanguageModelStreamPart, m as Retries, n as EmbeddingModelCallOptions, o as LanguageModelCallOptions, p as ResolvedModel, r as EmbeddingModelEmbed, s as LanguageModelGenerate, t as EmbeddingModel, u as ProviderOptions, v as RetryErrorAttempt, x as RetryableModelOptions, y as RetryResultAttempt } from "./types-D7G-2JLh.mjs";
|
|
2
2
|
import * as _ai_sdk_provider0 from "@ai-sdk/provider";
|
|
3
3
|
|
|
4
4
|
//#region src/create-retryable-model.d.ts
|
|
5
|
+
declare function createRetryable<MODEL extends LanguageModel>(options: Omit<RetryableModelOptions<LanguageModel>, 'model'> & {
|
|
6
|
+
model: GatewayLanguageModelId;
|
|
7
|
+
}): LanguageModel;
|
|
5
8
|
declare function createRetryable<MODEL extends LanguageModel>(options: RetryableModelOptions<MODEL>): LanguageModel;
|
|
6
9
|
declare function createRetryable<MODEL extends EmbeddingModel>(options: RetryableModelOptions<MODEL>): EmbeddingModel;
|
|
7
10
|
//#endregion
|
|
@@ -14,9 +17,9 @@ declare const getModelKey: (model: LanguageModel | EmbeddingModel) => string;
|
|
|
14
17
|
//#region src/utils.d.ts
|
|
15
18
|
declare const isObject: (value: unknown) => value is Record<string, unknown>;
|
|
16
19
|
declare const isString: (value: unknown) => value is string;
|
|
17
|
-
declare const
|
|
18
|
-
declare const
|
|
19
|
-
declare const
|
|
20
|
+
declare const isModel: (model: unknown) => model is LanguageModel | EmbeddingModel;
|
|
21
|
+
declare const isLanguageModel: (model: unknown) => model is LanguageModel;
|
|
22
|
+
declare const isEmbeddingModel: (model: unknown) => model is EmbeddingModel;
|
|
20
23
|
declare const isStreamResult: (result: LanguageModelGenerate | LanguageModelStream) => result is LanguageModelStream;
|
|
21
24
|
declare const isGenerateResult: (result: LanguageModelGenerate | LanguageModelStream) => result is LanguageModelGenerate;
|
|
22
25
|
/**
|
|
@@ -32,42 +35,32 @@ declare function isResultAttempt(attempt: RetryAttempt<any>): attempt is RetryRe
|
|
|
32
35
|
* These types are also emitted by `onChunk` callbacks.
|
|
33
36
|
* @see https://github.com/vercel/ai/blob/1fe4bd4144bff927f5319d9d206e782a73979ccb/packages/ai/src/generate-text/stream-text.ts#L686-L697
|
|
34
37
|
*/
|
|
35
|
-
declare const isStreamContentPart: (part: LanguageModelStreamPart) => part is _ai_sdk_provider0.
|
|
36
|
-
type: "tool-result";
|
|
37
|
-
toolCallId: string;
|
|
38
|
-
toolName: string;
|
|
39
|
-
result: unknown;
|
|
40
|
-
isError?: boolean;
|
|
41
|
-
providerExecuted?: boolean;
|
|
42
|
-
providerMetadata?: _ai_sdk_provider0.SharedV2ProviderMetadata;
|
|
43
|
-
} | {
|
|
38
|
+
declare const isStreamContentPart: (part: LanguageModelStreamPart) => part is _ai_sdk_provider0.LanguageModelV3Source | _ai_sdk_provider0.LanguageModelV3ToolCall | _ai_sdk_provider0.LanguageModelV3ToolResult | {
|
|
44
39
|
type: "text-delta";
|
|
45
40
|
id: string;
|
|
46
|
-
providerMetadata?: _ai_sdk_provider0.
|
|
41
|
+
providerMetadata?: _ai_sdk_provider0.SharedV3ProviderMetadata;
|
|
47
42
|
delta: string;
|
|
48
43
|
} | {
|
|
49
44
|
type: "reasoning-delta";
|
|
50
45
|
id: string;
|
|
51
|
-
providerMetadata?: _ai_sdk_provider0.
|
|
46
|
+
providerMetadata?: _ai_sdk_provider0.SharedV3ProviderMetadata;
|
|
52
47
|
delta: string;
|
|
53
48
|
} | {
|
|
54
49
|
type: "tool-input-start";
|
|
55
50
|
id: string;
|
|
56
51
|
toolName: string;
|
|
57
|
-
providerMetadata?: _ai_sdk_provider0.
|
|
52
|
+
providerMetadata?: _ai_sdk_provider0.SharedV3ProviderMetadata;
|
|
58
53
|
providerExecuted?: boolean;
|
|
54
|
+
dynamic?: boolean;
|
|
55
|
+
title?: string;
|
|
59
56
|
} | {
|
|
60
57
|
type: "tool-input-delta";
|
|
61
58
|
id: string;
|
|
62
59
|
delta: string;
|
|
63
|
-
providerMetadata?: _ai_sdk_provider0.
|
|
60
|
+
providerMetadata?: _ai_sdk_provider0.SharedV3ProviderMetadata;
|
|
64
61
|
} | {
|
|
65
62
|
type: "raw";
|
|
66
63
|
rawValue: unknown;
|
|
67
64
|
};
|
|
68
|
-
/**
|
|
69
|
-
* Type guard to check if a value is a Retry object (has a model property with a MODEL)
|
|
70
|
-
*/
|
|
71
|
-
declare const isRetry: <MODEL extends LanguageModel | EmbeddingModel>(value: unknown) => value is Retry<MODEL>;
|
|
72
65
|
//#endregion
|
|
73
|
-
export { EmbeddingModel, EmbeddingModelCallOptions, EmbeddingModelEmbed, LanguageModel, LanguageModelCallOptions, LanguageModelGenerate, LanguageModelStream, LanguageModelStreamPart, Retries, Retry, RetryAttempt, RetryContext, RetryErrorAttempt, RetryResultAttempt, Retryable, RetryableModelOptions, RetryableOptions, createRetryable, getModelKey,
|
|
66
|
+
export { EmbeddingModel, EmbeddingModelCallOptions, EmbeddingModelEmbed, GatewayLanguageModelId, LanguageModel, LanguageModelCallOptions, LanguageModelGenerate, LanguageModelStream, LanguageModelStreamPart, ProviderOptions, ResolvableLanguageModel, ResolvableModel, ResolvedModel, Retries, Retry, RetryAttempt, RetryContext, RetryErrorAttempt, RetryResultAttempt, Retryable, RetryableModelOptions, RetryableOptions, createRetryable, getModelKey, isEmbeddingModel, isErrorAttempt, isGenerateResult, isLanguageModel, isModel, isObject, isResultAttempt, isStreamContentPart, isStreamResult, isString };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as isModel, c as isStreamContentPart, i as isLanguageModel, l as isStreamResult, n as isErrorAttempt, o as isObject, r as isGenerateResult, s as isResultAttempt, t as isEmbeddingModel, u as isString } from "./utils-BXFlA2mh.mjs";
|
|
2
|
+
import { RetryError, gateway } from "ai";
|
|
2
3
|
import { delay } from "@ai-sdk/provider-utils";
|
|
3
4
|
import { getErrorMessage } from "@ai-sdk/provider";
|
|
4
|
-
import { RetryError } from "ai";
|
|
5
5
|
|
|
6
6
|
//#region src/calculate-exponential-backoff.ts
|
|
7
7
|
/**
|
|
@@ -27,6 +27,15 @@ function countModelAttempts(model, attempts) {
|
|
|
27
27
|
return attempts.filter((a) => getModelKey(a.model) === modelKey).length;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/resolve-model.ts
|
|
32
|
+
/**
|
|
33
|
+
* Resolve a model string via the AI SDK Gateway to a modelinstance
|
|
34
|
+
*/
|
|
35
|
+
function resolveModel(model) {
|
|
36
|
+
return isModel(model) ? model : gateway(model);
|
|
37
|
+
}
|
|
38
|
+
|
|
30
39
|
//#endregion
|
|
31
40
|
//#region src/find-retry-model.ts
|
|
32
41
|
/**
|
|
@@ -45,13 +54,19 @@ async function findRetryModel(retries, context) {
|
|
|
45
54
|
for (const retry of applicableRetries) {
|
|
46
55
|
let retryModel;
|
|
47
56
|
if (typeof retry === "function") retryModel = await retry(context);
|
|
48
|
-
else if (
|
|
57
|
+
else if (isObject(retry) && "model" in retry) retryModel = retry;
|
|
49
58
|
else retryModel = { model: retry };
|
|
50
59
|
if (retryModel) {
|
|
60
|
+
/**
|
|
61
|
+
* The model can be string or an instance.
|
|
62
|
+
* If it is a string, we need to resolve it to an instance.
|
|
63
|
+
*/
|
|
64
|
+
const modelValue = retryModel.model;
|
|
65
|
+
const resolvedModel = resolveModel(modelValue);
|
|
51
66
|
/**
|
|
52
67
|
* The model key uniquely identifies a model instance (provider + modelId)
|
|
53
68
|
*/
|
|
54
|
-
const retryModelKey = getModelKey(
|
|
69
|
+
const retryModelKey = getModelKey(resolvedModel);
|
|
55
70
|
/**
|
|
56
71
|
* Find all attempts with the same model
|
|
57
72
|
*/
|
|
@@ -60,7 +75,10 @@ async function findRetryModel(retries, context) {
|
|
|
60
75
|
/**
|
|
61
76
|
* Check if the model can still be retried based on maxAttempts
|
|
62
77
|
*/
|
|
63
|
-
if (retryAttempts.length < maxAttempts) return
|
|
78
|
+
if (retryAttempts.length < maxAttempts) return {
|
|
79
|
+
...retryModel,
|
|
80
|
+
model: resolvedModel
|
|
81
|
+
};
|
|
64
82
|
}
|
|
65
83
|
}
|
|
66
84
|
}
|
|
@@ -83,7 +101,7 @@ function prepareRetryError(error, attempts) {
|
|
|
83
101
|
//#endregion
|
|
84
102
|
//#region src/retryable-embedding-model.ts
|
|
85
103
|
var RetryableEmbeddingModel = class {
|
|
86
|
-
specificationVersion = "
|
|
104
|
+
specificationVersion = "v3";
|
|
87
105
|
baseModel;
|
|
88
106
|
currentModel;
|
|
89
107
|
options;
|
|
@@ -226,7 +244,7 @@ var RetryableEmbeddingModel = class {
|
|
|
226
244
|
//#endregion
|
|
227
245
|
//#region src/retryable-language-model.ts
|
|
228
246
|
var RetryableLanguageModel = class {
|
|
229
|
-
specificationVersion = "
|
|
247
|
+
specificationVersion = "v3";
|
|
230
248
|
baseModel;
|
|
231
249
|
currentModel;
|
|
232
250
|
options;
|
|
@@ -513,9 +531,16 @@ var RetryableLanguageModel = class {
|
|
|
513
531
|
//#endregion
|
|
514
532
|
//#region src/create-retryable-model.ts
|
|
515
533
|
function createRetryable(options) {
|
|
516
|
-
|
|
517
|
-
return new
|
|
534
|
+
const model = isModel(options.model) ? options.model : gateway(options.model);
|
|
535
|
+
if (isEmbeddingModel(model)) return new RetryableEmbeddingModel({
|
|
536
|
+
...options,
|
|
537
|
+
model
|
|
538
|
+
});
|
|
539
|
+
return new RetryableLanguageModel({
|
|
540
|
+
...options,
|
|
541
|
+
model
|
|
542
|
+
});
|
|
518
543
|
}
|
|
519
544
|
|
|
520
545
|
//#endregion
|
|
521
|
-
export { createRetryable, getModelKey,
|
|
546
|
+
export { createRetryable, getModelKey, isEmbeddingModel, isErrorAttempt, isGenerateResult, isLanguageModel, isModel, isObject, isResultAttempt, isStreamContentPart, isStreamResult, isString };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as RetryableOptions, b as Retryable, d as ResolvableLanguageModel, t as EmbeddingModel } from "../types-D7G-2JLh.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/retryables/content-filter-triggered.d.ts
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Fallback to a different model if the content filter was triggered.
|
|
7
7
|
*/
|
|
8
|
-
declare function contentFilterTriggered<MODEL extends
|
|
8
|
+
declare function contentFilterTriggered<MODEL extends ResolvableLanguageModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/retryables/request-not-retryable.d.ts
|
|
11
11
|
/**
|
|
12
12
|
* Fallback to a different model if the error is non-retryable.
|
|
13
13
|
*/
|
|
14
|
-
declare function requestNotRetryable<MODEL extends
|
|
14
|
+
declare function requestNotRetryable<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/retryables/request-timeout.d.ts
|
|
17
17
|
/**
|
|
@@ -19,7 +19,7 @@ declare function requestNotRetryable<MODEL extends LanguageModel | EmbeddingMode
|
|
|
19
19
|
* Use in combination with the `abortSignal` option.
|
|
20
20
|
* If no timeout is specified, a default of 60 seconds is used.
|
|
21
21
|
*/
|
|
22
|
-
declare function requestTimeout<MODEL extends
|
|
22
|
+
declare function requestTimeout<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/retryables/retry-after-delay.d.ts
|
|
25
25
|
/**
|
|
@@ -27,7 +27,7 @@ declare function requestTimeout<MODEL extends LanguageModel | EmbeddingModel>(mo
|
|
|
27
27
|
* Uses the `Retry-After` or `Retry-After-Ms` headers if present.
|
|
28
28
|
* Otherwise uses the specified `delay` and `backoffFactor` if provided.
|
|
29
29
|
*/
|
|
30
|
-
declare function retryAfterDelay<MODEL extends
|
|
30
|
+
declare function retryAfterDelay<MODEL extends ResolvableLanguageModel | EmbeddingModel>(options: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region src/retryables/service-overloaded.d.ts
|
|
33
33
|
/**
|
|
@@ -37,13 +37,13 @@ declare function retryAfterDelay<MODEL extends LanguageModel | EmbeddingModel>(o
|
|
|
37
37
|
* - Response with `type: "overloaded_error"`
|
|
38
38
|
* - Response with a `message` containing "overloaded"
|
|
39
39
|
*/
|
|
40
|
-
declare function serviceOverloaded<MODEL extends
|
|
40
|
+
declare function serviceOverloaded<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
41
41
|
//#endregion
|
|
42
42
|
//#region src/retryables/service-unavailable.d.ts
|
|
43
43
|
/**
|
|
44
44
|
* Fallback to a different model if the provider returns a service unavailable error.
|
|
45
45
|
* This retryable handles HTTP status code 503 (Service Unavailable).
|
|
46
46
|
*/
|
|
47
|
-
declare function serviceUnavailable<MODEL extends
|
|
47
|
+
declare function serviceUnavailable<MODEL extends ResolvableLanguageModel | EmbeddingModel>(model: MODEL, options?: RetryableOptions<MODEL>): Retryable<MODEL>;
|
|
48
48
|
//#endregion
|
|
49
49
|
export { contentFilterTriggered, requestNotRetryable, requestTimeout, retryAfterDelay, serviceOverloaded, serviceUnavailable };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isAbortError } from "@ai-sdk/provider-utils";
|
|
1
|
+
import { n as isErrorAttempt, o as isObject, s as isResultAttempt, u as isString } from "../utils-BXFlA2mh.mjs";
|
|
3
2
|
import { APICallError } from "ai";
|
|
3
|
+
import { isAbortError } from "@ai-sdk/provider-utils";
|
|
4
4
|
|
|
5
5
|
//#region src/retryables/content-filter-triggered.ts
|
|
6
6
|
/**
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { gateway } from "ai";
|
|
2
|
+
import { EmbeddingModelV3, LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3StreamPart, SharedV3ProviderOptions } from "@ai-sdk/provider";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
type Literals<T> = T extends string ? string extends T ? never : T : never;
|
|
6
|
+
type LanguageModel = LanguageModelV3;
|
|
7
|
+
type EmbeddingModel<VALUE = any> = EmbeddingModelV3<VALUE>;
|
|
8
|
+
type LanguageModelCallOptions = LanguageModelV3CallOptions;
|
|
9
|
+
type LanguageModelStreamPart = LanguageModelV3StreamPart;
|
|
10
|
+
type ProviderOptions = SharedV3ProviderOptions;
|
|
11
|
+
type GatewayLanguageModelId = Parameters<(typeof gateway)['languageModel']>[0];
|
|
12
|
+
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
|
+
/**
|
|
16
|
+
* Options for creating a retryable model.
|
|
17
|
+
*/
|
|
18
|
+
interface RetryableModelOptions<MODEL extends LanguageModel | EmbeddingModel> {
|
|
19
|
+
model: MODEL;
|
|
20
|
+
retries: Retries<MODEL>;
|
|
21
|
+
disabled?: boolean | (() => boolean);
|
|
22
|
+
onError?: (context: RetryContext<MODEL>) => void;
|
|
23
|
+
onRetry?: (context: RetryContext<MODEL>) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The context provided to Retryables with the current attempt and all previous attempts.
|
|
27
|
+
*/
|
|
28
|
+
type RetryContext<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
29
|
+
/**
|
|
30
|
+
* Current attempt that caused the retry
|
|
31
|
+
*/
|
|
32
|
+
current: RetryAttempt<ResolvedModel<MODEL>>;
|
|
33
|
+
/**
|
|
34
|
+
* All attempts made so far, including the current one
|
|
35
|
+
*/
|
|
36
|
+
attempts: Array<RetryAttempt<ResolvedModel<MODEL>>>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A retry attempt with an error
|
|
40
|
+
*/
|
|
41
|
+
type RetryErrorAttempt<MODEL extends LanguageModel | EmbeddingModel> = {
|
|
42
|
+
type: 'error';
|
|
43
|
+
error: unknown;
|
|
44
|
+
result?: undefined;
|
|
45
|
+
model: MODEL;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* A retry attempt with a successful result
|
|
49
|
+
*/
|
|
50
|
+
type RetryResultAttempt = {
|
|
51
|
+
type: 'result';
|
|
52
|
+
result: LanguageModelGenerate;
|
|
53
|
+
error?: undefined;
|
|
54
|
+
model: LanguageModel;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* A retry attempt with either an error or a result and the model used
|
|
58
|
+
*/
|
|
59
|
+
type RetryAttempt<MODEL extends LanguageModel | EmbeddingModel> = RetryErrorAttempt<MODEL> | RetryResultAttempt;
|
|
60
|
+
/**
|
|
61
|
+
* A model to retry with and the maximum number of attempts for that model.
|
|
62
|
+
*
|
|
63
|
+
* The model can be:
|
|
64
|
+
* - The exact MODEL type (instance)
|
|
65
|
+
* - A gateway string literal (for LanguageModel only)
|
|
66
|
+
* - A ResolvableModel<MODEL> (for compatibility with plain model arrays)
|
|
67
|
+
*
|
|
68
|
+
* This flexible approach allows retryable functions to return the exact model type
|
|
69
|
+
* they received without type assertions, while still supporting string-based gateway models.
|
|
70
|
+
*/
|
|
71
|
+
type Retry<MODEL extends ResolvableLanguageModel | EmbeddingModel> = {
|
|
72
|
+
model: MODEL;
|
|
73
|
+
maxAttempts?: number;
|
|
74
|
+
delay?: number;
|
|
75
|
+
backoffFactor?: number;
|
|
76
|
+
providerOptions?: ProviderOptions;
|
|
77
|
+
timeout?: number;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* A function that determines whether to retry with a different model based on the current attempt and all previous attempts.
|
|
81
|
+
*/
|
|
82
|
+
type Retryable<MODEL extends ResolvableLanguageModel | EmbeddingModel> = (context: RetryContext<MODEL>) => Retry<MODEL> | Promise<Retry<MODEL> | undefined> | undefined;
|
|
83
|
+
type Retries<MODEL extends LanguageModel | EmbeddingModel> = Array<Retryable<ResolvableModel<MODEL>> | Retry<ResolvableModel<MODEL>> | ResolvableModel<MODEL>>;
|
|
84
|
+
type RetryableOptions<MODEL extends ResolvableLanguageModel | EmbeddingModel> = Partial<Omit<Retry<MODEL>, 'model'>>;
|
|
85
|
+
type LanguageModelGenerate = Awaited<ReturnType<LanguageModel['doGenerate']>>;
|
|
86
|
+
type LanguageModelStream = Awaited<ReturnType<LanguageModel['doStream']>>;
|
|
87
|
+
type EmbeddingModelCallOptions<VALUE> = Parameters<EmbeddingModel<VALUE>['doEmbed']>[0];
|
|
88
|
+
type EmbeddingModelEmbed<VALUE = any> = Awaited<ReturnType<EmbeddingModel<VALUE>['doEmbed']>>;
|
|
89
|
+
//#endregion
|
|
90
|
+
export { RetryableOptions as S, RetryContext as _, LanguageModel as a, Retryable as b, LanguageModelStream as c, ResolvableLanguageModel as d, ResolvableModel as f, RetryAttempt as g, Retry as h, GatewayLanguageModelId as i, LanguageModelStreamPart as l, Retries as m, EmbeddingModelCallOptions as n, LanguageModelCallOptions as o, ResolvedModel as p, EmbeddingModelEmbed as r, LanguageModelGenerate as s, EmbeddingModel as t, ProviderOptions as u, RetryErrorAttempt as v, RetryableModelOptions as x, RetryResultAttempt as y };
|
|
@@ -1,9 +1,9 @@
|
|
|
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
|
|
5
|
-
const
|
|
6
|
-
const
|
|
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";
|
|
6
|
+
const isEmbeddingModel = (model) => isObject(model) && "provider" in model && "modelId" in model && "specificationVersion" in model && "doEmbed" in model && model.specificationVersion === "v3";
|
|
7
7
|
const isStreamResult = (result) => "stream" in result;
|
|
8
8
|
const isGenerateResult = (result) => "content" in result;
|
|
9
9
|
/**
|
|
@@ -26,10 +26,6 @@ function isResultAttempt(attempt) {
|
|
|
26
26
|
const isStreamContentPart = (part) => {
|
|
27
27
|
return part.type === "text-delta" || part.type === "reasoning-delta" || part.type === "source" || part.type === "tool-call" || part.type === "tool-result" || part.type === "tool-input-start" || part.type === "tool-input-delta" || part.type === "raw";
|
|
28
28
|
};
|
|
29
|
-
/**
|
|
30
|
-
* Type guard to check if a value is a Retry object (has a model property with a MODEL)
|
|
31
|
-
*/
|
|
32
|
-
const isRetry = (value) => isObject(value) && "model" in value && isModelV2(value.model);
|
|
33
29
|
|
|
34
30
|
//#endregion
|
|
35
|
-
export {
|
|
31
|
+
export { isModel as a, isStreamContentPart as c, isLanguageModel as i, isStreamResult as l, isErrorAttempt as n, isObject as o, isGenerateResult as r, isResultAttempt as s, isEmbeddingModel as t, isString as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-retry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
4
|
"description": "AI SDK Retry",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -30,20 +30,22 @@
|
|
|
30
30
|
"url": "git+https://github.com/zirkelc/ai-retry.git"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"ai": "
|
|
33
|
+
"ai": "6.x"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@ai-sdk/anthropic": "
|
|
37
|
-
"@ai-sdk/azure": "
|
|
38
|
-
"@ai-sdk/
|
|
39
|
-
"@ai-sdk/
|
|
36
|
+
"@ai-sdk/anthropic": "3.0.0-beta.59",
|
|
37
|
+
"@ai-sdk/azure": "3.0.0-beta.68",
|
|
38
|
+
"@ai-sdk/gateway": "2.0.0-beta.66",
|
|
39
|
+
"@ai-sdk/groq": "3.0.0-beta.36",
|
|
40
|
+
"@ai-sdk/openai": "3.0.0-beta.66",
|
|
41
|
+
"@ai-sdk/test-server": "1.0.0-beta.1",
|
|
40
42
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
41
|
-
"@biomejs/biome": "^2.
|
|
43
|
+
"@biomejs/biome": "^2.3.7",
|
|
42
44
|
"@total-typescript/tsconfig": "^1.0.4",
|
|
43
|
-
"@types/node": "^24.
|
|
44
|
-
"ai": "
|
|
45
|
+
"@types/node": "^24.10.1",
|
|
46
|
+
"ai": "6.0.0-beta.116",
|
|
45
47
|
"husky": "^9.1.7",
|
|
46
|
-
"msw": "^2.
|
|
48
|
+
"msw": "^2.12.3",
|
|
47
49
|
"pkg-pr-new": "^0.0.60",
|
|
48
50
|
"publint": "^0.3.15",
|
|
49
51
|
"tsdown": "^0.16.7",
|
|
@@ -53,8 +55,8 @@
|
|
|
53
55
|
"zod": "^4.1.13"
|
|
54
56
|
},
|
|
55
57
|
"dependencies": {
|
|
56
|
-
"@ai-sdk/provider": "
|
|
57
|
-
"@ai-sdk/provider-utils": "
|
|
58
|
+
"@ai-sdk/provider": "3.0.0-beta.17",
|
|
59
|
+
"@ai-sdk/provider-utils": "4.0.0-beta.34"
|
|
58
60
|
},
|
|
59
61
|
"scripts": {
|
|
60
62
|
"build": "tsdown",
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { ProviderOptions } from "@ai-sdk/provider-utils";
|
|
2
|
-
import { EmbeddingModelV2, LanguageModelV2, LanguageModelV2CallOptions, LanguageModelV2StreamPart } from "@ai-sdk/provider";
|
|
3
|
-
|
|
4
|
-
//#region src/types.d.ts
|
|
5
|
-
type LanguageModel = LanguageModelV2;
|
|
6
|
-
type EmbeddingModel<VALUE = unknown> = EmbeddingModelV2<VALUE>;
|
|
7
|
-
type LanguageModelCallOptions = LanguageModelV2CallOptions;
|
|
8
|
-
type LanguageModelStreamPart = LanguageModelV2StreamPart;
|
|
9
|
-
/**
|
|
10
|
-
* Options for creating a retryable model.
|
|
11
|
-
*/
|
|
12
|
-
interface RetryableModelOptions<MODEL extends LanguageModel | EmbeddingModel> {
|
|
13
|
-
model: MODEL;
|
|
14
|
-
retries: Retries<MODEL>;
|
|
15
|
-
disabled?: boolean | (() => boolean);
|
|
16
|
-
onError?: (context: RetryContext<MODEL>) => void;
|
|
17
|
-
onRetry?: (context: RetryContext<MODEL>) => void;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* The context provided to Retryables with the current attempt and all previous attempts.
|
|
21
|
-
*/
|
|
22
|
-
type RetryContext<MODEL extends LanguageModel | EmbeddingModel> = {
|
|
23
|
-
/**
|
|
24
|
-
* Current attempt that caused the retry
|
|
25
|
-
*/
|
|
26
|
-
current: RetryAttempt<MODEL>;
|
|
27
|
-
/**
|
|
28
|
-
* All attempts made so far, including the current one
|
|
29
|
-
*/
|
|
30
|
-
attempts: Array<RetryAttempt<MODEL>>;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* A retry attempt with an error
|
|
34
|
-
*/
|
|
35
|
-
type RetryErrorAttempt<MODEL extends LanguageModel | EmbeddingModel> = {
|
|
36
|
-
type: 'error';
|
|
37
|
-
error: unknown;
|
|
38
|
-
result?: undefined;
|
|
39
|
-
model: MODEL;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* A retry attempt with a successful result
|
|
43
|
-
*/
|
|
44
|
-
type RetryResultAttempt = {
|
|
45
|
-
type: 'result';
|
|
46
|
-
result: LanguageModelGenerate;
|
|
47
|
-
error?: undefined;
|
|
48
|
-
model: LanguageModel;
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* A retry attempt with either an error or a result and the model used
|
|
52
|
-
*/
|
|
53
|
-
type RetryAttempt<MODEL extends LanguageModel | EmbeddingModel> = RetryErrorAttempt<MODEL> | RetryResultAttempt;
|
|
54
|
-
/**
|
|
55
|
-
* A model to retry with and the maximum number of attempts for that model.
|
|
56
|
-
*/
|
|
57
|
-
type Retry<MODEL extends LanguageModel | EmbeddingModel> = {
|
|
58
|
-
model: MODEL;
|
|
59
|
-
maxAttempts?: number;
|
|
60
|
-
delay?: number;
|
|
61
|
-
backoffFactor?: number;
|
|
62
|
-
providerOptions?: ProviderOptions;
|
|
63
|
-
timeout?: number;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* A function that determines whether to retry with a different model based on the current attempt and all previous attempts.
|
|
67
|
-
*/
|
|
68
|
-
type Retryable<MODEL extends LanguageModel | EmbeddingModel> = (context: RetryContext<MODEL>) => Retry<MODEL> | Promise<Retry<MODEL> | undefined> | undefined;
|
|
69
|
-
type Retries<MODEL extends LanguageModel | EmbeddingModel> = Array<Retryable<MODEL> | Retry<MODEL> | MODEL>;
|
|
70
|
-
type RetryableOptions<MODEL extends LanguageModel | EmbeddingModel> = Partial<Omit<Retry<MODEL>, 'model'>>;
|
|
71
|
-
type LanguageModelGenerate = Awaited<ReturnType<LanguageModel['doGenerate']>>;
|
|
72
|
-
type LanguageModelStream = Awaited<ReturnType<LanguageModel['doStream']>>;
|
|
73
|
-
type EmbeddingModelCallOptions<VALUE> = Parameters<EmbeddingModel<VALUE>['doEmbed']>[0];
|
|
74
|
-
type EmbeddingModelEmbed<VALUE = any> = Awaited<ReturnType<EmbeddingModel<VALUE>['doEmbed']>>;
|
|
75
|
-
//#endregion
|
|
76
|
-
export { RetryableOptions as _, LanguageModelCallOptions as a, LanguageModelStreamPart as c, RetryAttempt as d, RetryContext as f, RetryableModelOptions as g, Retryable as h, LanguageModel as i, Retries as l, RetryResultAttempt as m, EmbeddingModelCallOptions as n, LanguageModelGenerate as o, RetryErrorAttempt as p, EmbeddingModelEmbed as r, LanguageModelStream as s, EmbeddingModel as t, Retry as u };
|