ai-retry 1.9.0 → 1.10.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 +30 -0
- package/dist/{create-retryable-model-VgywojZt.mjs → create-retryable-model-D36IQyOQ.mjs} +137 -45
- package/dist/{error-CoF13EJO.d.mts → error-B-rjhfG_.d.mts} +1 -1
- package/dist/experimental/embedding-model/index.d.mts +2 -2
- package/dist/experimental/embedding-model/index.mjs +1 -1
- package/dist/experimental/embedding-model/retryables/index.d.mts +2 -2
- package/dist/experimental/image-model/index.d.mts +3 -3
- package/dist/experimental/image-model/index.mjs +1 -1
- package/dist/experimental/image-model/retryables/index.d.mts +3 -3
- package/dist/experimental/language-model/index.d.mts +3 -3
- package/dist/experimental/language-model/index.mjs +1 -1
- package/dist/experimental/language-model/retryables/index.d.mts +3 -3
- package/dist/{index-K7qV8HD9.d.mts → index-DaJrd4dN.d.mts} +2 -2
- package/dist/{index-D4w-HLk-.d.mts → index-ewZ5T6B2.d.mts} +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/retryables/index.d.mts +1 -1
- package/dist/{types-ydxC71oc.d.mts → types-Dik-mH20.d.mts} +29 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1026,6 +1026,7 @@ You can use the following callbacks to log retry attempts and errors:
|
|
|
1026
1026
|
- `onError` is invoked if an error occurs.
|
|
1027
1027
|
- `onRetry` is invoked before attempting a retry.
|
|
1028
1028
|
- `onSuccess` is invoked after a successful request with the model that handled it.
|
|
1029
|
+
- `onFailure` is invoked when the request ultimately fails and no retry could recover it.
|
|
1029
1030
|
|
|
1030
1031
|
```typescript
|
|
1031
1032
|
const retryableModel = createRetryable({
|
|
@@ -1049,9 +1050,17 @@ const retryableModel = createRetryable({
|
|
|
1049
1050
|
`Request handled by ${context.current.model.provider}/${context.current.model.modelId}`,
|
|
1050
1051
|
);
|
|
1051
1052
|
},
|
|
1053
|
+
onFailure: (context) => {
|
|
1054
|
+
console.error(
|
|
1055
|
+
`Request failed after ${context.attempts.length} attempts:`,
|
|
1056
|
+
context.error,
|
|
1057
|
+
);
|
|
1058
|
+
},
|
|
1052
1059
|
});
|
|
1053
1060
|
```
|
|
1054
1061
|
|
|
1062
|
+
`onSuccess` and `onFailure` are counterparts: exactly one of them is invoked per request once its final outcome is known. `onFailure` fires when the error could not be recovered by a retry, whether because no retryable matched, all retries were exhausted, or the retry itself failed. `context.error` is the error surfaced to the caller (a [`RetryError`](#all-retries-failed) wrapping every attempt error when more than one attempt was made, otherwise the original error), and `context.current` is the final failed attempt. Neither callback fires when retries are disabled.
|
|
1063
|
+
|
|
1055
1064
|
#### Reset
|
|
1056
1065
|
|
|
1057
1066
|
By default, every new request starts with the base model, even if a previous request was retried with a different model. The `reset` option changes this behavior by making the last successfully retried model **sticky**, that means subsequent requests will continue using that model instead of switching back to the base model. The reset value controls how long the retry model stays sticky before resetting back to the base model.
|
|
@@ -1183,6 +1192,13 @@ In the second case, errors during stream processing will not always be retried,
|
|
|
1183
1192
|
> [!IMPORTANT]
|
|
1184
1193
|
> **Streaming limitation:** Retries and fallbacks only apply before the first content chunk is emitted. Once streaming begins delivering content, the response is committed to the current model. Mid-stream errors will propagate to the caller rather than triggering a fallback. If reliable retries are critical for your use case, consider using `generateText` instead of `streamText`.
|
|
1185
1194
|
|
|
1195
|
+
#### Preamble buffering
|
|
1196
|
+
|
|
1197
|
+
Every stream begins with a non-content preamble (`stream-start`, then optionally `response-metadata` and `text-start` / `reasoning-start`) that providers emit as soon as the response headers arrive, before any content flows. Because a retry can still happen during this window, `ai-retry` does not forward the preamble immediately. It buffers the leading non-content parts and flushes them only when the first content chunk arrives (or when the stream finishes with no content). If a retry fires before any content, the buffered preamble is discarded and replaced by the fallback's, so the consumer always sees exactly one preamble — the one belonging to the model that actually produced the output, with its own `warnings` and `response-metadata`. Without this, a fallback's `stream-start` would be emitted a second time after the primary's, which some consumers (e.g. `streamText`) reject.
|
|
1198
|
+
|
|
1199
|
+
> [!NOTE]
|
|
1200
|
+
> One side effect: the consumer's "stream started" signal now arrives at first-content time rather than when the response headers arrive (typically a sub-second difference). For UIs that show a typing indicator off `stream-start` this is negligible.
|
|
1201
|
+
|
|
1186
1202
|
### API Reference
|
|
1187
1203
|
|
|
1188
1204
|
#### `createRetryable(options: RetryableModelOptions): LanguageModelV3 | EmbeddingModelV3 | ImageModelV3`
|
|
@@ -1203,6 +1219,7 @@ interface RetryableModelOptions<
|
|
|
1203
1219
|
context: RetryContext<MODEL>,
|
|
1204
1220
|
) => void | OnRetryOverrides<MODEL> | Promise<void | OnRetryOverrides<MODEL>>;
|
|
1205
1221
|
onSuccess?: (context: SuccessContext<MODEL>) => void;
|
|
1222
|
+
onFailure?: (context: FailureContext<MODEL>) => void;
|
|
1206
1223
|
}
|
|
1207
1224
|
```
|
|
1208
1225
|
|
|
@@ -1216,6 +1233,7 @@ interface RetryableModelOptions<
|
|
|
1216
1233
|
- `onError`: Callback invoked when an error occurs.
|
|
1217
1234
|
- `onRetry`: Callback invoked before attempting a retry. May optionally return an `OnRetryOverrides` object (or a `Promise` of one) to override `options.*` for the upcoming attempt only. See [Dynamic Call Options via `onRetry`](#dynamic-call-options-via-onretry).
|
|
1218
1235
|
- `onSuccess`: Callback invoked after a successful request. Receives the model that handled the request and all previous attempts.
|
|
1236
|
+
- `onFailure`: Callback invoked when the request ultimately fails and no retry could recover it (no retryable matched, all retries exhausted, or the retry itself failed).
|
|
1219
1237
|
|
|
1220
1238
|
#### `Reset`
|
|
1221
1239
|
|
|
@@ -1302,6 +1320,18 @@ interface SuccessAttempt {
|
|
|
1302
1320
|
}
|
|
1303
1321
|
```
|
|
1304
1322
|
|
|
1323
|
+
#### `FailureContext`
|
|
1324
|
+
|
|
1325
|
+
The `FailureContext` object is passed to the `onFailure` callback when a request ultimately fails. `current` is the final failed attempt (an error attempt, see [`RetryAttempt`](#retryattempt)) and `error` is the error surfaced to the caller, a [`RetryError`](#all-retries-failed) wrapping every attempt error when more than one attempt was made, otherwise the original error.
|
|
1326
|
+
|
|
1327
|
+
```typescript
|
|
1328
|
+
interface FailureContext {
|
|
1329
|
+
current: RetryErrorAttempt;
|
|
1330
|
+
attempts: Array<RetryAttempt>;
|
|
1331
|
+
error: unknown;
|
|
1332
|
+
}
|
|
1333
|
+
```
|
|
1334
|
+
|
|
1305
1335
|
#### `RetryAttempt`
|
|
1306
1336
|
|
|
1307
1337
|
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.
|
|
@@ -515,14 +515,13 @@ var RetryableEmbeddingModel = class extends BaseRetryableModel {
|
|
|
515
515
|
callOptions: retryCallOptions
|
|
516
516
|
};
|
|
517
517
|
} catch (error) {
|
|
518
|
+
const { retryModel, attempt, finalError } = await this.handleError(error, attempts, retryCallOptions);
|
|
519
|
+
attempts.push(attempt);
|
|
518
520
|
/**
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
+
* No retry matched. Record the attempt as failed and throw the
|
|
522
|
+
* surfaced error.
|
|
521
523
|
*/
|
|
522
|
-
|
|
523
|
-
try {
|
|
524
|
-
decision = await this.handleError(error, attempts, retryCallOptions);
|
|
525
|
-
} catch (finalError) {
|
|
524
|
+
if (!retryModel) {
|
|
526
525
|
input.recorder?.endAttempt({
|
|
527
526
|
attempt: attemptNumber,
|
|
528
527
|
outcome: "failure",
|
|
@@ -530,8 +529,6 @@ var RetryableEmbeddingModel = class extends BaseRetryableModel {
|
|
|
530
529
|
});
|
|
531
530
|
throw finalError;
|
|
532
531
|
}
|
|
533
|
-
const { retryModel, attempt } = decision;
|
|
534
|
-
attempts.push(attempt);
|
|
535
532
|
/**
|
|
536
533
|
* If the inbound abort signal is already aborted and the chosen
|
|
537
534
|
* retry does not supply a fresh deadline, the retry would die
|
|
@@ -587,19 +584,26 @@ var RetryableEmbeddingModel = class extends BaseRetryableModel {
|
|
|
587
584
|
};
|
|
588
585
|
this.options.onError?.(context);
|
|
589
586
|
const retryModel = await findRetryModel(this.options.retries, context);
|
|
590
|
-
/**
|
|
591
|
-
* Handler didn't return any models to try next, rethrow the error.
|
|
592
|
-
* If we retried the request, wrap the error into a `RetryError` for better visibility.
|
|
593
|
-
*/
|
|
594
|
-
if (!retryModel) {
|
|
595
|
-
if (updatedAttempts.length > 1) throw prepareRetryError(error, updatedAttempts);
|
|
596
|
-
throw error;
|
|
597
|
-
}
|
|
598
587
|
return {
|
|
599
588
|
retryModel,
|
|
600
|
-
attempt: errorAttempt
|
|
589
|
+
attempt: errorAttempt,
|
|
590
|
+
finalError: retryModel ? void 0 : updatedAttempts.length > 1 ? prepareRetryError(error, updatedAttempts) : error
|
|
601
591
|
};
|
|
602
592
|
}
|
|
593
|
+
/**
|
|
594
|
+
* Fire the `onFailure` callback for a terminally failed operation. The
|
|
595
|
+
* final attempt (last entry of `attempts`) is surfaced as `current`.
|
|
596
|
+
*/
|
|
597
|
+
emitFailure(attempts, error) {
|
|
598
|
+
if (!this.options.onFailure) return;
|
|
599
|
+
const current = attempts.at(-1);
|
|
600
|
+
if (!current) return;
|
|
601
|
+
this.options.onFailure({
|
|
602
|
+
current,
|
|
603
|
+
attempts,
|
|
604
|
+
error
|
|
605
|
+
});
|
|
606
|
+
}
|
|
603
607
|
async doEmbed(callOptions) {
|
|
604
608
|
/**
|
|
605
609
|
* Resolve the starting model (base or sticky)
|
|
@@ -616,13 +620,19 @@ var RetryableEmbeddingModel = class extends BaseRetryableModel {
|
|
|
616
620
|
provider: startModel.provider,
|
|
617
621
|
modelId: startModel.modelId
|
|
618
622
|
});
|
|
623
|
+
/**
|
|
624
|
+
* Shared attempts array, threaded into `withRetry` so it stays populated
|
|
625
|
+
* (including the final failed attempt) when the retry loop throws.
|
|
626
|
+
*/
|
|
627
|
+
const attempts = [];
|
|
619
628
|
let operationError;
|
|
620
629
|
try {
|
|
621
|
-
const { result,
|
|
630
|
+
const { result, callOptions: finalCallOptions } = await this.withRetry({
|
|
622
631
|
fn: async (retryCallOptions) => {
|
|
623
632
|
return this.currentModel.doEmbed(retryCallOptions);
|
|
624
633
|
},
|
|
625
634
|
callOptions,
|
|
635
|
+
attempts,
|
|
626
636
|
recorder
|
|
627
637
|
});
|
|
628
638
|
this.updateStickyModel(startModel);
|
|
@@ -638,6 +648,7 @@ var RetryableEmbeddingModel = class extends BaseRetryableModel {
|
|
|
638
648
|
return result;
|
|
639
649
|
} catch (error) {
|
|
640
650
|
operationError = error;
|
|
651
|
+
this.emitFailure(attempts, error);
|
|
641
652
|
throw error;
|
|
642
653
|
} finally {
|
|
643
654
|
recorder?.endOperation({
|
|
@@ -729,14 +740,13 @@ var RetryableImageModel = class extends BaseRetryableModel {
|
|
|
729
740
|
callOptions: retryCallOptions
|
|
730
741
|
};
|
|
731
742
|
} catch (error) {
|
|
743
|
+
const { retryModel, attempt, finalError } = await this.handleError(error, attempts, retryCallOptions);
|
|
744
|
+
attempts.push(attempt);
|
|
732
745
|
/**
|
|
733
|
-
*
|
|
734
|
-
*
|
|
746
|
+
* No retry matched. Record the attempt as failed and throw the
|
|
747
|
+
* surfaced error.
|
|
735
748
|
*/
|
|
736
|
-
|
|
737
|
-
try {
|
|
738
|
-
decision = await this.handleError(error, attempts, retryCallOptions);
|
|
739
|
-
} catch (finalError) {
|
|
749
|
+
if (!retryModel) {
|
|
740
750
|
input.recorder?.endAttempt({
|
|
741
751
|
attempt: attemptNumber,
|
|
742
752
|
outcome: "failure",
|
|
@@ -744,8 +754,6 @@ var RetryableImageModel = class extends BaseRetryableModel {
|
|
|
744
754
|
});
|
|
745
755
|
throw finalError;
|
|
746
756
|
}
|
|
747
|
-
const { retryModel, attempt } = decision;
|
|
748
|
-
attempts.push(attempt);
|
|
749
757
|
/**
|
|
750
758
|
* If the inbound abort signal is already aborted and the chosen
|
|
751
759
|
* retry does not supply a fresh deadline, the retry would die
|
|
@@ -801,19 +809,26 @@ var RetryableImageModel = class extends BaseRetryableModel {
|
|
|
801
809
|
};
|
|
802
810
|
this.options.onError?.(context);
|
|
803
811
|
const retryModel = await findRetryModel(this.options.retries, context);
|
|
804
|
-
/**
|
|
805
|
-
* Handler didn't return any models to try next, rethrow the error.
|
|
806
|
-
* If we retried the request, wrap the error into a `RetryError` for better visibility.
|
|
807
|
-
*/
|
|
808
|
-
if (!retryModel) {
|
|
809
|
-
if (updatedAttempts.length > 1) throw prepareRetryError(error, updatedAttempts);
|
|
810
|
-
throw error;
|
|
811
|
-
}
|
|
812
812
|
return {
|
|
813
813
|
retryModel,
|
|
814
|
-
attempt: errorAttempt
|
|
814
|
+
attempt: errorAttempt,
|
|
815
|
+
finalError: retryModel ? void 0 : updatedAttempts.length > 1 ? prepareRetryError(error, updatedAttempts) : error
|
|
815
816
|
};
|
|
816
817
|
}
|
|
818
|
+
/**
|
|
819
|
+
* Fire the `onFailure` callback for a terminally failed operation. The
|
|
820
|
+
* final attempt (last entry of `attempts`) is surfaced as `current`.
|
|
821
|
+
*/
|
|
822
|
+
emitFailure(attempts, error) {
|
|
823
|
+
if (!this.options.onFailure) return;
|
|
824
|
+
const current = attempts.at(-1);
|
|
825
|
+
if (!current) return;
|
|
826
|
+
this.options.onFailure({
|
|
827
|
+
current,
|
|
828
|
+
attempts,
|
|
829
|
+
error
|
|
830
|
+
});
|
|
831
|
+
}
|
|
817
832
|
async doGenerate(callOptions) {
|
|
818
833
|
/**
|
|
819
834
|
* Resolve the starting model (base or sticky)
|
|
@@ -830,13 +845,19 @@ var RetryableImageModel = class extends BaseRetryableModel {
|
|
|
830
845
|
provider: startModel.provider,
|
|
831
846
|
modelId: startModel.modelId
|
|
832
847
|
});
|
|
848
|
+
/**
|
|
849
|
+
* Shared attempts array, threaded into `withRetry` so it stays populated
|
|
850
|
+
* (including the final failed attempt) when the retry loop throws.
|
|
851
|
+
*/
|
|
852
|
+
const attempts = [];
|
|
833
853
|
let operationError;
|
|
834
854
|
try {
|
|
835
|
-
const { result,
|
|
855
|
+
const { result, callOptions: finalCallOptions } = await this.withRetry({
|
|
836
856
|
fn: async (retryCallOptions) => {
|
|
837
857
|
return this.currentModel.doGenerate(retryCallOptions);
|
|
838
858
|
},
|
|
839
859
|
callOptions,
|
|
860
|
+
attempts,
|
|
840
861
|
recorder
|
|
841
862
|
});
|
|
842
863
|
this.updateStickyModel(startModel);
|
|
@@ -852,6 +873,7 @@ var RetryableImageModel = class extends BaseRetryableModel {
|
|
|
852
873
|
return result;
|
|
853
874
|
} catch (error) {
|
|
854
875
|
operationError = error;
|
|
876
|
+
this.emitFailure(attempts, error);
|
|
855
877
|
throw error;
|
|
856
878
|
} finally {
|
|
857
879
|
recorder?.endOperation({
|
|
@@ -1080,6 +1102,20 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1080
1102
|
finalError: retryModel ? void 0 : updatedAttempts.length > 1 ? prepareRetryError(error, updatedAttempts) : error
|
|
1081
1103
|
};
|
|
1082
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Fire the `onFailure` callback for a terminally failed operation. The
|
|
1107
|
+
* final attempt (last entry of `attempts`) is surfaced as `current`.
|
|
1108
|
+
*/
|
|
1109
|
+
emitFailure(attempts, error) {
|
|
1110
|
+
if (!this.options.onFailure) return;
|
|
1111
|
+
const current = attempts.at(-1);
|
|
1112
|
+
if (!current || !isErrorAttempt(current)) return;
|
|
1113
|
+
this.options.onFailure({
|
|
1114
|
+
current,
|
|
1115
|
+
attempts,
|
|
1116
|
+
error
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1083
1119
|
async doGenerate(callOptions) {
|
|
1084
1120
|
/**
|
|
1085
1121
|
* Resolve the starting model (base or sticky)
|
|
@@ -1096,13 +1132,19 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1096
1132
|
provider: startModel.provider,
|
|
1097
1133
|
modelId: startModel.modelId
|
|
1098
1134
|
});
|
|
1135
|
+
/**
|
|
1136
|
+
* Shared attempts array, threaded into `withRetry` so it stays populated
|
|
1137
|
+
* (including the final failed attempt) when the retry loop throws.
|
|
1138
|
+
*/
|
|
1139
|
+
const attempts = [];
|
|
1099
1140
|
let operationError;
|
|
1100
1141
|
try {
|
|
1101
|
-
const { result,
|
|
1142
|
+
const { result, callOptions: finalCallOptions } = await this.withRetry({
|
|
1102
1143
|
fn: async (retryCallOptions) => {
|
|
1103
1144
|
return this.currentModel.doGenerate(retryCallOptions);
|
|
1104
1145
|
},
|
|
1105
1146
|
callOptions,
|
|
1147
|
+
attempts,
|
|
1106
1148
|
recorder
|
|
1107
1149
|
});
|
|
1108
1150
|
this.updateStickyModel(startModel);
|
|
@@ -1118,6 +1160,7 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1118
1160
|
return result;
|
|
1119
1161
|
} catch (error) {
|
|
1120
1162
|
operationError = error;
|
|
1163
|
+
this.emitFailure(attempts, error);
|
|
1121
1164
|
throw error;
|
|
1122
1165
|
} finally {
|
|
1123
1166
|
recorder?.endOperation({
|
|
@@ -1147,7 +1190,11 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1147
1190
|
* Perform the initial call to doStream with retry logic to handle errors before any data is streamed.
|
|
1148
1191
|
*/
|
|
1149
1192
|
let result;
|
|
1150
|
-
|
|
1193
|
+
/**
|
|
1194
|
+
* Shared attempts array, threaded into `withRetry` so it stays populated
|
|
1195
|
+
* (including the final failed attempt) when the retry loop throws.
|
|
1196
|
+
*/
|
|
1197
|
+
let attempts = [];
|
|
1151
1198
|
let finalCallOptions;
|
|
1152
1199
|
/**
|
|
1153
1200
|
* The open attempt span for the stream currently being consumed, closed
|
|
@@ -1160,6 +1207,7 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1160
1207
|
return this.currentModel.doStream(retryCallOptions);
|
|
1161
1208
|
},
|
|
1162
1209
|
callOptions,
|
|
1210
|
+
attempts,
|
|
1163
1211
|
recorder
|
|
1164
1212
|
});
|
|
1165
1213
|
result = initial.result;
|
|
@@ -1171,6 +1219,7 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1171
1219
|
* Every pre-stream attempt failed; record the operation failure before
|
|
1172
1220
|
* the error propagates to the caller.
|
|
1173
1221
|
*/
|
|
1222
|
+
this.emitFailure(attempts, error);
|
|
1174
1223
|
recorder?.endOperation({
|
|
1175
1224
|
provider: this.currentModel.provider,
|
|
1176
1225
|
modelId: this.currentModel.modelId,
|
|
@@ -1202,6 +1251,16 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1202
1251
|
let capturedWarnings = [];
|
|
1203
1252
|
let capturedResponseMetadata = {};
|
|
1204
1253
|
/**
|
|
1254
|
+
* Buffer for the leading non-content parts (`stream-start`,
|
|
1255
|
+
* `response-metadata`, `text-start`, `reasoning-start`, …) of this
|
|
1256
|
+
* attempt. While no content has been forwarded the preamble is held
|
|
1257
|
+
* here rather than enqueued, so a pre-content retry can discard it
|
|
1258
|
+
* and the consumer sees exactly one preamble — the one belonging to
|
|
1259
|
+
* the model that actually produced the output. Reset per attempt;
|
|
1260
|
+
* flushed on the first content part or at completion.
|
|
1261
|
+
*/
|
|
1262
|
+
let preambleBuffer = [];
|
|
1263
|
+
/**
|
|
1205
1264
|
* Set when a `finish` part triggers a retry decision. Causes the
|
|
1206
1265
|
* inner read loop to exit without enqueuing the finish part, and
|
|
1207
1266
|
* the outer loop to re-stream against the next model.
|
|
@@ -1270,11 +1329,25 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1270
1329
|
}
|
|
1271
1330
|
}
|
|
1272
1331
|
/**
|
|
1273
|
-
* Mark that streaming has started once we receive actual
|
|
1332
|
+
* Mark that streaming has started once we receive actual
|
|
1333
|
+
* content. On the first content part, flush this attempt's
|
|
1334
|
+
* buffered preamble (in order) ahead of the content, then
|
|
1335
|
+
* forward normally from here on.
|
|
1274
1336
|
*/
|
|
1275
|
-
if (isStreamContentPart(value))
|
|
1276
|
-
|
|
1277
|
-
|
|
1337
|
+
if (isStreamContentPart(value)) {
|
|
1338
|
+
isStreaming = true;
|
|
1339
|
+
for (const buffered of preambleBuffer) controller.enqueue(buffered);
|
|
1340
|
+
preambleBuffer = [];
|
|
1341
|
+
controller.enqueue(value);
|
|
1342
|
+
} else if (!isStreaming)
|
|
1343
|
+
/**
|
|
1344
|
+
* Pre-content part: buffer it so a pre-content retry can
|
|
1345
|
+
* replace it with the next attempt's preamble.
|
|
1346
|
+
*/
|
|
1347
|
+
preambleBuffer.push(value);
|
|
1348
|
+
else
|
|
1349
|
+
/**
|
|
1350
|
+
* Content already flowing: forward directly.
|
|
1278
1351
|
*/
|
|
1279
1352
|
controller.enqueue(value);
|
|
1280
1353
|
}
|
|
@@ -1306,7 +1379,13 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1306
1379
|
currentRetry,
|
|
1307
1380
|
recorder
|
|
1308
1381
|
});
|
|
1309
|
-
|
|
1382
|
+
/**
|
|
1383
|
+
* Cancelling a reader whose stream has already errored (e.g.
|
|
1384
|
+
* a mid-stream `controller.error`) rejects with that stored
|
|
1385
|
+
* error. Swallow it: the retry already succeeded and that
|
|
1386
|
+
* rejection must not abort the wrapped stream.
|
|
1387
|
+
*/
|
|
1388
|
+
await reader?.cancel().catch(() => {});
|
|
1310
1389
|
result = retriedResult.result;
|
|
1311
1390
|
attempts = retriedResult.attempts;
|
|
1312
1391
|
finalCallOptions = retriedResult.callOptions;
|
|
@@ -1318,6 +1397,13 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1318
1397
|
outcome: "success",
|
|
1319
1398
|
finishReason: streamFinishReason
|
|
1320
1399
|
});
|
|
1400
|
+
/**
|
|
1401
|
+
* A stream that completes with no content part still has its
|
|
1402
|
+
* preamble buffered. Flush it so a zero-content completion emits
|
|
1403
|
+
* its `stream-start` (and any metadata/finish) before closing.
|
|
1404
|
+
*/
|
|
1405
|
+
for (const buffered of preambleBuffer) controller.enqueue(buffered);
|
|
1406
|
+
preambleBuffer = [];
|
|
1321
1407
|
controller.close();
|
|
1322
1408
|
break;
|
|
1323
1409
|
} catch (error) {
|
|
@@ -1349,6 +1435,7 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1349
1435
|
error
|
|
1350
1436
|
});
|
|
1351
1437
|
operationError = finalError;
|
|
1438
|
+
this.emitFailure(attempts, finalError);
|
|
1352
1439
|
controller.enqueue({
|
|
1353
1440
|
type: "error",
|
|
1354
1441
|
error: finalError
|
|
@@ -1369,6 +1456,7 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1369
1456
|
error
|
|
1370
1457
|
});
|
|
1371
1458
|
operationError = error;
|
|
1459
|
+
this.emitFailure(attempts, error);
|
|
1372
1460
|
controller.enqueue({
|
|
1373
1461
|
type: "error",
|
|
1374
1462
|
error
|
|
@@ -1408,9 +1496,13 @@ var RetryableLanguageModel = class extends BaseRetryableModel {
|
|
|
1408
1496
|
recorder
|
|
1409
1497
|
});
|
|
1410
1498
|
/**
|
|
1411
|
-
* Cancel the previous reader and stream if we are retrying
|
|
1499
|
+
* Cancel the previous reader and stream if we are retrying.
|
|
1500
|
+
* Cancelling a reader whose stream has already errored (e.g. a
|
|
1501
|
+
* mid-stream `controller.error`) rejects with that stored
|
|
1502
|
+
* error. Swallow it: the retry already succeeded and that
|
|
1503
|
+
* rejection must not abort the wrapped stream.
|
|
1412
1504
|
*/
|
|
1413
|
-
await reader?.cancel();
|
|
1505
|
+
await reader?.cancel().catch(() => {});
|
|
1414
1506
|
result = retriedResult.result;
|
|
1415
1507
|
attempts = retriedResult.attempts;
|
|
1416
1508
|
finalCallOptions = retriedResult.callOptions;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as RetryContext, D as Retry, P as Retryable, S as ResolvableLanguageModel, c as ImageModel, n as EmbeddingModel } from "./types-Dik-mH20.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/experimental/internal/condition.d.ts
|
|
4
4
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "../../error-
|
|
1
|
+
import { F as RetryableModelOptions, n as EmbeddingModel } from "../../types-Dik-mH20.mjs";
|
|
2
|
+
import "../../error-B-rjhfG_.mjs";
|
|
3
3
|
import { aborted, error, httpStatus, timeout } from "./retryables/index.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/experimental/embedding-model/index.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createRetryable$1 } from "../../create-retryable-model-
|
|
1
|
+
import { t as createRetryable$1 } from "../../create-retryable-model-D36IQyOQ.mjs";
|
|
2
2
|
import "../../error-CaTT-xX8.mjs";
|
|
3
3
|
import { aborted, error, httpStatus, timeout } from "./retryables/index.mjs";
|
|
4
4
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as Condition, t as StatusPattern } from "../../../error-
|
|
1
|
+
import { A as RetryContext } from "../../../types-Dik-mH20.mjs";
|
|
2
|
+
import { n as Condition, t as StatusPattern } from "../../../error-B-rjhfG_.mjs";
|
|
3
3
|
import * as _ai_sdk_provider0 from "@ai-sdk/provider";
|
|
4
4
|
|
|
5
5
|
//#region src/experimental/embedding-model/retryables/index.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "../../error-
|
|
3
|
-
import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../index-
|
|
1
|
+
import { F as RetryableModelOptions, c as ImageModel } from "../../types-Dik-mH20.mjs";
|
|
2
|
+
import "../../error-B-rjhfG_.mjs";
|
|
3
|
+
import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../index-ewZ5T6B2.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/experimental/image-model/index.d.ts
|
|
6
6
|
declare function createRetryable<MODEL extends ImageModel>(options: RetryableModelOptions<MODEL>): ImageModel;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createRetryable$1 } from "../../create-retryable-model-
|
|
1
|
+
import { t as createRetryable$1 } from "../../create-retryable-model-D36IQyOQ.mjs";
|
|
2
2
|
import "../../error-CaTT-xX8.mjs";
|
|
3
3
|
import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../retryables-CPAbu_M3.mjs";
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../../../types-
|
|
2
|
-
import "../../../error-
|
|
3
|
-
import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../../index-
|
|
1
|
+
import "../../../types-Dik-mH20.mjs";
|
|
2
|
+
import "../../../error-B-rjhfG_.mjs";
|
|
3
|
+
import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../../index-ewZ5T6B2.mjs";
|
|
4
4
|
export { aborted, error, httpStatus, noImage, timeout };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "../../error-
|
|
3
|
-
import { a as result, i as httpStatus, n as error, o as schemaInvalid, r as finishReason, s as timeout, t as aborted } from "../../index-
|
|
1
|
+
import { F as RetryableModelOptions, f as LanguageModel, s as GatewayLanguageModelId } from "../../types-Dik-mH20.mjs";
|
|
2
|
+
import "../../error-B-rjhfG_.mjs";
|
|
3
|
+
import { a as result, i as httpStatus, n as error, o as schemaInvalid, r as finishReason, s as timeout, t as aborted } from "../../index-DaJrd4dN.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/experimental/language-model/index.d.ts
|
|
6
6
|
declare function createRetryable(options: Omit<RetryableModelOptions<LanguageModel>, 'model'> & {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createRetryable$1 } from "../../create-retryable-model-
|
|
1
|
+
import { t as createRetryable$1 } from "../../create-retryable-model-D36IQyOQ.mjs";
|
|
2
2
|
import "../../error-CaTT-xX8.mjs";
|
|
3
3
|
import { a as result, i as httpStatus, n as error, o as schemaInvalid, r as finishReason, s as timeout, t as aborted } from "../../retryables-M5l_6w9k.mjs";
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../../../types-
|
|
2
|
-
import "../../../error-
|
|
3
|
-
import { a as result, i as httpStatus, n as error, o as schemaInvalid, r as finishReason, s as timeout, t as aborted } from "../../../index-
|
|
1
|
+
import "../../../types-Dik-mH20.mjs";
|
|
2
|
+
import "../../../error-B-rjhfG_.mjs";
|
|
3
|
+
import { a as result, i as httpStatus, n as error, o as schemaInvalid, r as finishReason, s as timeout, t as aborted } from "../../../index-DaJrd4dN.mjs";
|
|
4
4
|
export { aborted, error, finishReason, httpStatus, result, schemaInvalid, timeout };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as Condition, t as StatusPattern } from "./error-
|
|
1
|
+
import { A as RetryContext, S as ResolvableLanguageModel, h as LanguageModelResult } from "./types-Dik-mH20.mjs";
|
|
2
|
+
import { n as Condition, t as StatusPattern } from "./error-B-rjhfG_.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/experimental/internal/result.d.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as Condition, t as StatusPattern } from "./error-
|
|
1
|
+
import { A as RetryContext, c as ImageModel } from "./types-Dik-mH20.mjs";
|
|
2
|
+
import { n as Condition, t as StatusPattern } from "./error-B-rjhfG_.mjs";
|
|
3
3
|
import * as _ai_sdk_provider13 from "@ai-sdk/provider";
|
|
4
4
|
|
|
5
5
|
//#region src/experimental/internal/no-image.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as RetryContext, C as ResolvableModel, D as Retry, E as Retries, F as RetryableModelOptions, I as RetryableOptions, L as SuccessAttempt, M as RetryResultAttempt, N as RetryTelemetrySettings, O as RetryAttempt, P as Retryable, R as SuccessContext, S as ResolvableLanguageModel, T as Result, _ as LanguageModelStream, a as EmbeddingModelRetryCallOptions, b as ProviderOptions, c as ImageModel, d as ImageModelRetryCallOptions, f as LanguageModel, g as LanguageModelRetryCallOptions, h as LanguageModelResult, i as EmbeddingModelEmbed, j as RetryErrorAttempt, k as RetryCallOptions, l as ImageModelCallOptions, m as LanguageModelGenerate, n as EmbeddingModel, o as FailureContext, p as LanguageModelCallOptions, r as EmbeddingModelCallOptions, s as GatewayLanguageModelId, t as CallOptions, u as ImageModelGenerate, v as LanguageModelStreamPart, w as ResolvedModel, x as Reset, y as OnRetryOverrides } from "./types-Dik-mH20.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/create-retryable-model.d.ts
|
|
4
4
|
declare function createRetryable<MODEL extends LanguageModel>(options: Omit<RetryableModelOptions<LanguageModel>, 'model'> & {
|
|
@@ -24,4 +24,4 @@ declare function isErrorAttempt(attempt: RetryAttempt<any>): attempt is RetryErr
|
|
|
24
24
|
*/
|
|
25
25
|
declare function isResultAttempt(attempt: RetryAttempt<any>): attempt is RetryResultAttempt;
|
|
26
26
|
//#endregion
|
|
27
|
-
export { CallOptions, EmbeddingModel, EmbeddingModelCallOptions, EmbeddingModelEmbed, EmbeddingModelRetryCallOptions, GatewayLanguageModelId, ImageModel, ImageModelCallOptions, ImageModelGenerate, ImageModelRetryCallOptions, LanguageModel, LanguageModelCallOptions, LanguageModelGenerate, LanguageModelResult, LanguageModelRetryCallOptions, LanguageModelStream, LanguageModelStreamPart, OnRetryOverrides, ProviderOptions, Reset, ResolvableLanguageModel, ResolvableModel, ResolvedModel, Result, Retries, Retry, RetryAttempt, RetryCallOptions, RetryContext, RetryErrorAttempt, RetryResultAttempt, RetryTelemetrySettings, Retryable, RetryableModelOptions, RetryableOptions, SuccessAttempt, SuccessContext, createRetryable, getModelKey, isErrorAttempt, isResultAttempt };
|
|
27
|
+
export { CallOptions, EmbeddingModel, EmbeddingModelCallOptions, EmbeddingModelEmbed, EmbeddingModelRetryCallOptions, FailureContext, GatewayLanguageModelId, ImageModel, ImageModelCallOptions, ImageModelGenerate, ImageModelRetryCallOptions, LanguageModel, LanguageModelCallOptions, LanguageModelGenerate, LanguageModelResult, LanguageModelRetryCallOptions, LanguageModelStream, LanguageModelStreamPart, OnRetryOverrides, ProviderOptions, Reset, ResolvableLanguageModel, ResolvableModel, ResolvedModel, Result, Retries, Retry, RetryAttempt, RetryCallOptions, RetryContext, RetryErrorAttempt, RetryResultAttempt, RetryTelemetrySettings, Retryable, RetryableModelOptions, RetryableOptions, SuccessAttempt, SuccessContext, createRetryable, getModelKey, isErrorAttempt, isResultAttempt };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as getModelKey, t as createRetryable } from "./create-retryable-model-
|
|
1
|
+
import { n as getModelKey, t as createRetryable } from "./create-retryable-model-D36IQyOQ.mjs";
|
|
2
2
|
import { n as isErrorAttempt, s as isResultAttempt } from "./guards-D8UJtxDK.mjs";
|
|
3
3
|
|
|
4
4
|
export { createRetryable, getModelKey, isErrorAttempt, isResultAttempt };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as RetryableOptions, P as Retryable, S as ResolvableLanguageModel, c as ImageModel, n as EmbeddingModel } from "../types-Dik-mH20.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/retryables/content-filter-triggered.d.ts
|
|
4
4
|
/**
|
|
@@ -113,6 +113,26 @@ type SuccessContext<MODEL extends ResolvableLanguageModel | EmbeddingModel | Ima
|
|
|
113
113
|
*/
|
|
114
114
|
attempts: Array<RetryAttempt<ResolvedModel<MODEL>>>;
|
|
115
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* The context provided to onFailure when an operation terminally fails
|
|
118
|
+
* (no retry matched, retries exhausted, or the retry itself failed).
|
|
119
|
+
*/
|
|
120
|
+
type FailureContext<MODEL extends ResolvableLanguageModel | EmbeddingModel | ImageModel> = {
|
|
121
|
+
/**
|
|
122
|
+
* The final attempt that failed.
|
|
123
|
+
*/
|
|
124
|
+
current: RetryErrorAttempt<ResolvedModel<MODEL>>;
|
|
125
|
+
/**
|
|
126
|
+
* All attempts made, including the final failed one.
|
|
127
|
+
*/
|
|
128
|
+
attempts: Array<RetryAttempt<ResolvedModel<MODEL>>>;
|
|
129
|
+
/**
|
|
130
|
+
* The error surfaced to the caller. When more than one attempt was made,
|
|
131
|
+
* this is a `RetryError` wrapping every attempt error; otherwise the raw
|
|
132
|
+
* error.
|
|
133
|
+
*/
|
|
134
|
+
error: unknown;
|
|
135
|
+
};
|
|
116
136
|
/**
|
|
117
137
|
* Telemetry configuration for retry instrumentation.
|
|
118
138
|
*
|
|
@@ -180,6 +200,14 @@ interface RetryableModelOptions<MODEL extends LanguageModel | EmbeddingModel | I
|
|
|
180
200
|
*/
|
|
181
201
|
onRetry?: (context: RetryContext<MODEL>) => void | OnRetryOverrides<MODEL> | Promise<void | OnRetryOverrides<MODEL>>;
|
|
182
202
|
onSuccess?: (context: SuccessContext<MODEL>) => void;
|
|
203
|
+
/**
|
|
204
|
+
* Called once when an operation terminally fails and the error could not
|
|
205
|
+
* be recovered by a retry: no retry matched, all retries were exhausted,
|
|
206
|
+
* or the retry itself failed. The counterpart to `onSuccess`.
|
|
207
|
+
*
|
|
208
|
+
* Not called when retries are disabled.
|
|
209
|
+
*/
|
|
210
|
+
onFailure?: (context: FailureContext<MODEL>) => void;
|
|
183
211
|
}
|
|
184
212
|
/**
|
|
185
213
|
* A model to retry with and the maximum number of attempts for that model.
|
|
@@ -243,4 +271,4 @@ type EmbeddingModelCallOptions = Parameters<EmbeddingModel['doEmbed']>[0];
|
|
|
243
271
|
type EmbeddingModelEmbed = Awaited<ReturnType<EmbeddingModel['doEmbed']>>;
|
|
244
272
|
type ImageModelGenerate = Awaited<ReturnType<ImageModel['doGenerate']>>;
|
|
245
273
|
//#endregion
|
|
246
|
-
export {
|
|
274
|
+
export { RetryContext as A, ResolvableModel as C, Retry as D, Retries as E, RetryableModelOptions as F, RetryableOptions as I, SuccessAttempt as L, RetryResultAttempt as M, RetryTelemetrySettings as N, RetryAttempt as O, Retryable as P, SuccessContext as R, ResolvableLanguageModel as S, Result as T, LanguageModelStream as _, EmbeddingModelRetryCallOptions as a, ProviderOptions as b, ImageModel as c, ImageModelRetryCallOptions as d, LanguageModel as f, LanguageModelRetryCallOptions as g, LanguageModelResult as h, EmbeddingModelEmbed as i, RetryErrorAttempt as j, RetryCallOptions as k, ImageModelCallOptions as l, LanguageModelGenerate as m, EmbeddingModel as n, FailureContext as o, LanguageModelCallOptions as p, EmbeddingModelCallOptions as r, GatewayLanguageModelId as s, CallOptions as t, ImageModelGenerate as u, LanguageModelStreamPart as v, ResolvedModel as w, Reset as x, OnRetryOverrides as y };
|