ai-retry 1.8.0 → 1.9.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 CHANGED
@@ -1141,28 +1141,28 @@ ai_retry.doGenerate outcome=success, attempts=2
1141
1141
 
1142
1142
  **Operation span** attributes:
1143
1143
 
1144
- | Attribute | Description |
1145
- | -------------------------------------------------------- | ------------------------------------------------------- |
1146
- | `ai_retry.operation` | `doGenerate`, `doStream`, or `doEmbed` |
1147
- | `ai_retry.outcome` | `success` or `failure` |
1148
- | `ai_retry.attempts` | total number of attempts |
1149
- | `ai_retry.model.start` | the model the request started with (`provider/modelId`) |
1150
- | `ai_retry.model.final` | the model that produced the final outcome |
1151
- | `ai_retry.error.{name,message,cause.name,cause.message}` | the failing error (on failure) |
1152
- | `ai_retry.function.id`, `ai_retry.metadata.*` | from the telemetry settings |
1144
+ | Attribute | Description |
1145
+ | --------------------------------------------------------------- | ---------------------------------------------------------------------------- |
1146
+ | `ai_retry.operation` | `doGenerate`, `doStream`, or `doEmbed` |
1147
+ | `ai_retry.outcome` | `success` or `failure` |
1148
+ | `ai_retry.attempts` | total number of attempts |
1149
+ | `ai_retry.model.start` | the model the request started with (`provider/modelId`) |
1150
+ | `ai_retry.model.final` | the model that produced the final outcome |
1151
+ | `ai_retry.error.{name,message,status,cause.name,cause.message,cause.status}` | the failing error (on failure); `status` when it carries an HTTP status code |
1152
+ | `ai_retry.function.id`, `ai_retry.metadata.*` | from the telemetry settings |
1153
1153
 
1154
1154
  **Attempt span** (`ai_retry.attempt`) attributes:
1155
1155
 
1156
- | Attribute | Description |
1157
- | ---------------------------------------------------------------- | ----------------------------------------- |
1158
- | `ai_retry.attempt.number` | 1-based attempt index |
1159
- | `ai_retry.attempt.model` | model used (`provider/modelId`) |
1160
- | `ai_retry.attempt.outcome` | `success`, `retry`, or `failure` |
1161
- | `ai_retry.attempt.type` | `result` or `error` |
1162
- | `ai_retry.attempt.finish_reason` | finish reason (result attempts) |
1163
- | `ai_retry.attempt.delay_ms` | backoff scheduled before the next attempt |
1164
- | `ai_retry.attempt.timeout_ms` | timeout budget, when the retry set one |
1165
- | `ai_retry.attempt.error.{name,message,cause.name,cause.message}` | the error (error attempts) |
1156
+ | Attribute | Description |
1157
+ | ----------------------------------------------------------------------- | ------------------------------------------------------------------------ |
1158
+ | `ai_retry.attempt.number` | 1-based attempt index |
1159
+ | `ai_retry.attempt.model` | model used (`provider/modelId`) |
1160
+ | `ai_retry.attempt.outcome` | `success`, `retry`, or `failure` |
1161
+ | `ai_retry.attempt.type` | `result` or `error` |
1162
+ | `ai_retry.attempt.finish_reason` | finish reason (result attempts) |
1163
+ | `ai_retry.attempt.delay_ms` | backoff scheduled before the next attempt |
1164
+ | `ai_retry.attempt.timeout_ms` | timeout budget, when the retry set one |
1165
+ | `ai_retry.attempt.error.{name,message,status,cause.name,cause.message,cause.status}` | the error (error attempts); `status` when it carries an HTTP status code |
1166
1166
 
1167
1167
  Attempt spans also carry the standard `gen_ai.request.model` / `gen_ai.provider.name` attributes so observability tools (Langfuse, etc.) recognize and render them.
1168
1168
 
@@ -311,13 +311,18 @@ function loadOtelApi() {
311
311
  return otelApiPromise;
312
312
  }
313
313
  /**
314
- * Coarse error label for the `*.error.name` / `*.error.cause.name` attributes.
315
- * Matches the SDK's habit of using the error class name (e.g. `AI_APICallError`,
316
- * `TimeoutError`).
314
+ * Normalize an unknown thrown value into the fields recorded on error spans:
315
+ * - `name`: the error class name (e.g. `AI_APICallError`, `TimeoutError`), or
316
+ * `typeof` for non-`Error` values.
317
+ * - `message`: the error message.
318
+ * - `status`: HTTP status code, when the error carries one (e.g. `APICallError`).
317
319
  */
318
- function errorType(error) {
319
- if (error instanceof Error) return error.name;
320
- return typeof error;
320
+ function describeError(error) {
321
+ return {
322
+ name: error instanceof Error ? error.name : typeof error,
323
+ message: error instanceof Error ? error.message : String(error),
324
+ status: typeof error === "object" && error !== null && "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : void 0
325
+ };
321
326
  }
322
327
  /**
323
328
  * Translates retry telemetry events into OpenTelemetry spans.
@@ -394,18 +399,22 @@ var OpenTelemetrySink = class {
394
399
  }
395
400
  #recordError(span, error, errorAttribute) {
396
401
  const exception = error instanceof Error ? error : new Error(String(error));
397
- span.setAttribute(`${errorAttribute}.name`, errorType(error));
398
- span.setAttribute(`${errorAttribute}.message`, exception.message);
402
+ const info = describeError(error);
403
+ span.setAttribute(`${errorAttribute}.name`, info.name);
404
+ span.setAttribute(`${errorAttribute}.message`, info.message);
405
+ if (info.status !== void 0) span.setAttribute(`${errorAttribute}.status`, info.status);
399
406
  /** One level of the error chain — the underlying cause, when present. */
400
407
  const cause = error instanceof Error ? error.cause : void 0;
401
408
  if (cause !== void 0) {
402
- span.setAttribute(`${errorAttribute}.cause.name`, errorType(cause));
403
- span.setAttribute(`${errorAttribute}.cause.message`, cause instanceof Error ? cause.message : String(cause));
409
+ const causeInfo = describeError(cause);
410
+ span.setAttribute(`${errorAttribute}.cause.name`, causeInfo.name);
411
+ span.setAttribute(`${errorAttribute}.cause.message`, causeInfo.message);
412
+ if (causeInfo.status !== void 0) span.setAttribute(`${errorAttribute}.cause.status`, causeInfo.status);
404
413
  }
405
414
  span.recordException(exception);
406
415
  span.setStatus({
407
416
  code: this.#api.SpanStatusCode.ERROR,
408
- message: exception.message
417
+ message: info.message
409
418
  });
410
419
  }
411
420
  };
@@ -1,4 +1,4 @@
1
- import { t as createRetryable$1 } from "../../create-retryable-model-BdA-OoIc.mjs";
1
+ import { t as createRetryable$1 } from "../../create-retryable-model-VgywojZt.mjs";
2
2
  import "../../error-CaTT-xX8.mjs";
3
3
  import { aborted, error, httpStatus, timeout } from "./retryables/index.mjs";
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { k as RetryContext } from "../../../types-ydxC71oc.mjs";
2
2
  import { n as Condition, t as StatusPattern } from "../../../error-CoF13EJO.mjs";
3
- import * as _ai_sdk_provider13 from "@ai-sdk/provider";
3
+ import * as _ai_sdk_provider0 from "@ai-sdk/provider";
4
4
 
5
5
  //#region src/experimental/embedding-model/retryables/index.d.ts
6
6
  /**
@@ -11,10 +11,10 @@ import * as _ai_sdk_provider13 from "@ai-sdk/provider";
11
11
  * from 'ai-retry/experimental/embedding-model/retryables';
12
12
  */
13
13
  declare const error: {
14
- <MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3, E = unknown>(predicate: (err: E, ctx: RetryContext<MODEL>) => boolean | Promise<boolean>): Condition<MODEL>;
15
- isRetryable<MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3>(flag?: boolean): Condition<MODEL>;
16
- statusCode<MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3>(...patterns: Array<number | RegExp>): Condition<MODEL>;
17
- message<MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3>(...patterns: Array<string | RegExp>): Condition<MODEL>;
18
- }, httpStatus: <MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3>(...patterns: Array<StatusPattern>) => Condition<MODEL>, timeout: <MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3>() => Condition<MODEL>, aborted: <MODEL extends _ai_sdk_provider13.EmbeddingModelV3 = _ai_sdk_provider13.EmbeddingModelV3>() => Condition<MODEL>;
14
+ <MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3, E = unknown>(predicate: (err: E, ctx: RetryContext<MODEL>) => boolean | Promise<boolean>): Condition<MODEL>;
15
+ isRetryable<MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3>(flag?: boolean): Condition<MODEL>;
16
+ statusCode<MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3>(...patterns: Array<number | RegExp>): Condition<MODEL>;
17
+ message<MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3>(...patterns: Array<string | RegExp>): Condition<MODEL>;
18
+ }, httpStatus: <MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3>(...patterns: Array<StatusPattern>) => Condition<MODEL>, timeout: <MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3>() => Condition<MODEL>, aborted: <MODEL extends _ai_sdk_provider0.EmbeddingModelV3 = _ai_sdk_provider0.EmbeddingModelV3>() => Condition<MODEL>;
19
19
  //#endregion
20
20
  export { aborted, error, httpStatus, timeout };
@@ -1,6 +1,6 @@
1
1
  import { P as RetryableModelOptions, s as ImageModel } from "../../types-ydxC71oc.mjs";
2
2
  import "../../error-CoF13EJO.mjs";
3
- import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../index-CTbSMr1u.mjs";
3
+ import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../index-D4w-HLk-.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-BdA-OoIc.mjs";
1
+ import { t as createRetryable$1 } from "../../create-retryable-model-VgywojZt.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
1
  import "../../../types-ydxC71oc.mjs";
2
2
  import "../../../error-CoF13EJO.mjs";
3
- import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../../index-CTbSMr1u.mjs";
3
+ import { a as noImage, i as timeout, n as error, r as httpStatus, t as aborted } from "../../../index-D4w-HLk-.mjs";
4
4
  export { aborted, error, httpStatus, noImage, timeout };
@@ -1,4 +1,4 @@
1
- import { t as createRetryable$1 } from "../../create-retryable-model-BdA-OoIc.mjs";
1
+ import { t as createRetryable$1 } from "../../create-retryable-model-VgywojZt.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
 
@@ -0,0 +1,34 @@
1
+ import { k as RetryContext, s as ImageModel } from "./types-ydxC71oc.mjs";
2
+ import { n as Condition, t as StatusPattern } from "./error-CoF13EJO.mjs";
3
+ import * as _ai_sdk_provider13 from "@ai-sdk/provider";
4
+
5
+ //#region src/experimental/internal/no-image.d.ts
6
+ /**
7
+ * Match when image generation produced no images
8
+ * (`NoImageGeneratedError`).
9
+ *
10
+ * **Important:** returns a `Condition`, not a `Retryable`. Call
11
+ * `.switch()` or `.retry()` to plug it into `retries: [...]`.
12
+ *
13
+ * @example
14
+ * noImage().switch({ model: fallback })
15
+ * noImage().retry({ maxAttempts: 3 })
16
+ */
17
+ declare function noImage<MODEL extends ImageModel = ImageModel>(): Condition<MODEL>;
18
+ //#endregion
19
+ //#region src/experimental/image-model/retryables/index.d.ts
20
+ /**
21
+ * Experimental composable conditions bound to `ImageModel`. For use with
22
+ * `generateImage`.
23
+ *
24
+ * import { error, noImage, ... }
25
+ * from 'ai-retry/experimental/image-model/retryables';
26
+ */
27
+ declare const error: {
28
+ <MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3, E = unknown>(predicate: (err: E, ctx: RetryContext<MODEL>) => boolean | Promise<boolean>): Condition<MODEL>;
29
+ isRetryable<MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3>(flag?: boolean): Condition<MODEL>;
30
+ statusCode<MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3>(...patterns: Array<number | RegExp>): Condition<MODEL>;
31
+ message<MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3>(...patterns: Array<string | RegExp>): Condition<MODEL>;
32
+ }, httpStatus: <MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3>(...patterns: Array<StatusPattern>) => Condition<MODEL>, timeout: <MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3>() => Condition<MODEL>, aborted: <MODEL extends _ai_sdk_provider13.ImageModelV3 = _ai_sdk_provider13.ImageModelV3>() => Condition<MODEL>;
33
+ //#endregion
34
+ export { noImage as a, timeout as i, error as n, httpStatus as r, aborted as t };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as getModelKey, t as createRetryable } from "./create-retryable-model-BdA-OoIc.mjs";
1
+ import { n as getModelKey, t as createRetryable } from "./create-retryable-model-VgywojZt.mjs";
2
2
  import { n as isErrorAttempt, s as isResultAttempt } from "./guards-D8UJtxDK.mjs";
3
3
 
4
4
  export { createRetryable, getModelKey, isErrorAttempt, isResultAttempt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-retry",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Retry and fallback mechanisms for AI SDK",
5
5
  "keywords": [
6
6
  "ai",
@@ -1,34 +0,0 @@
1
- import { k as RetryContext, s as ImageModel } from "./types-ydxC71oc.mjs";
2
- import { n as Condition, t as StatusPattern } from "./error-CoF13EJO.mjs";
3
- import * as _ai_sdk_provider0 from "@ai-sdk/provider";
4
-
5
- //#region src/experimental/internal/no-image.d.ts
6
- /**
7
- * Match when image generation produced no images
8
- * (`NoImageGeneratedError`).
9
- *
10
- * **Important:** returns a `Condition`, not a `Retryable`. Call
11
- * `.switch()` or `.retry()` to plug it into `retries: [...]`.
12
- *
13
- * @example
14
- * noImage().switch({ model: fallback })
15
- * noImage().retry({ maxAttempts: 3 })
16
- */
17
- declare function noImage<MODEL extends ImageModel = ImageModel>(): Condition<MODEL>;
18
- //#endregion
19
- //#region src/experimental/image-model/retryables/index.d.ts
20
- /**
21
- * Experimental composable conditions bound to `ImageModel`. For use with
22
- * `generateImage`.
23
- *
24
- * import { error, noImage, ... }
25
- * from 'ai-retry/experimental/image-model/retryables';
26
- */
27
- declare const error: {
28
- <MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3, E = unknown>(predicate: (err: E, ctx: RetryContext<MODEL>) => boolean | Promise<boolean>): Condition<MODEL>;
29
- isRetryable<MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3>(flag?: boolean): Condition<MODEL>;
30
- statusCode<MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3>(...patterns: Array<number | RegExp>): Condition<MODEL>;
31
- message<MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3>(...patterns: Array<string | RegExp>): Condition<MODEL>;
32
- }, httpStatus: <MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3>(...patterns: Array<StatusPattern>) => Condition<MODEL>, timeout: <MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3>() => Condition<MODEL>, aborted: <MODEL extends _ai_sdk_provider0.ImageModelV3 = _ai_sdk_provider0.ImageModelV3>() => Condition<MODEL>;
33
- //#endregion
34
- export { noImage as a, timeout as i, error as n, httpStatus as r, aborted as t };