ai-retry 1.7.4 → 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 +81 -0
- package/dist/{create-retryable-model-Bgf7SQFz.mjs → create-retryable-model-VgywojZt.mjs} +707 -270
- package/dist/{error-CPbAtI-h.d.mts → error-CoF13EJO.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 +8 -8
- 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-D4w-HLk-.d.mts +34 -0
- package/dist/{index-BygX0XfC.d.mts → index-K7qV8HD9.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-DYMm5YMu.d.mts → types-ydxC71oc.d.mts} +41 -1
- package/package.json +13 -1
- package/dist/index-CNEL_aJP.d.mts +0 -34
package/README.md
CHANGED
|
@@ -1092,6 +1092,85 @@ const retryableModel = createRetryable({
|
|
|
1092
1092
|
});
|
|
1093
1093
|
```
|
|
1094
1094
|
|
|
1095
|
+
### Telemetry
|
|
1096
|
+
|
|
1097
|
+
> [!NOTE]
|
|
1098
|
+
> Experimental: Span names and attributes may change in patch versions.
|
|
1099
|
+
|
|
1100
|
+
`ai-retry` can emit [OpenTelemetry](https://opentelemetry.io/) spans for each request and every retry attempt. The spans are created on the active OpenTelemetry context, so they nest automatically under the AI SDK's own spans (e.g. `ai.generateText.doGenerate`) when you also enable `experimental_telemetry` on `generateText`/`streamText`. A single trace then shows the individual attempts — which model each used, why it was retried, and the backoff between them — that the SDK's own span otherwise hides.
|
|
1101
|
+
|
|
1102
|
+
#### Setup
|
|
1103
|
+
|
|
1104
|
+
Telemetry uses the optional peer dependency `@opentelemetry/api` (already present if you use the AI SDK). Register an OpenTelemetry SDK once at startup, then opt in per model:
|
|
1105
|
+
|
|
1106
|
+
```typescript
|
|
1107
|
+
import { createRetryable } from 'ai-retry';
|
|
1108
|
+
|
|
1109
|
+
const retryableModel = createRetryable({
|
|
1110
|
+
model: openai('gpt-4o'),
|
|
1111
|
+
retries: [anthropic('claude-sonnet-4-5')],
|
|
1112
|
+
experimental_telemetry: { isEnabled: true },
|
|
1113
|
+
});
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
The settings mirror the AI SDK's `experimental_telemetry` shape:
|
|
1117
|
+
|
|
1118
|
+
```ts
|
|
1119
|
+
interface RetryTelemetrySettings {
|
|
1120
|
+
isEnabled?: boolean; // off by default while experimental
|
|
1121
|
+
tracer?: Tracer; // defaults to trace.getTracer('ai-retry')
|
|
1122
|
+
functionId?: string; // groups telemetry by function
|
|
1123
|
+
metadata?: Record<string, AttributeValue>;
|
|
1124
|
+
}
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
Spans are emitted only when `isEnabled` is `true`. By default the global tracer is used, which is a no-op until an OpenTelemetry SDK is registered — so enabling it in code that runs without an SDK has no effect and no cost.
|
|
1128
|
+
|
|
1129
|
+
> [!NOTE]
|
|
1130
|
+
> Prompts and generated content are **not** recorded — only metadata (models, outcomes, errors, timing). The AI SDK's own telemetry records the prompt/response on its spans when you enable `recordInputs`/`recordOutputs`.
|
|
1131
|
+
|
|
1132
|
+
#### Spans
|
|
1133
|
+
|
|
1134
|
+
Each request creates one operation span (`ai_retry.doGenerate`, `ai_retry.doStream`, or `ai_retry.doEmbed`) with one child `ai_retry.attempt` span per attempt:
|
|
1135
|
+
|
|
1136
|
+
```
|
|
1137
|
+
ai_retry.doGenerate outcome=success, attempts=2
|
|
1138
|
+
├─ ai_retry.attempt #1 outcome=retry, type=error (529 → fallback)
|
|
1139
|
+
└─ ai_retry.attempt #2 outcome=success, type=result
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
**Operation span** attributes:
|
|
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,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
|
+
|
|
1154
|
+
**Attempt span** (`ai_retry.attempt`) attributes:
|
|
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,status,cause.name,cause.message,cause.status}` | the error (error attempts); `status` when it carries an HTTP status code |
|
|
1166
|
+
|
|
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
|
+
|
|
1169
|
+
> [!NOTE]
|
|
1170
|
+
> **Streaming:** retries only happen before the first content chunk (see [Streaming](#streaming)), so a `ai_retry.doStream` attempt is marked `success` once content begins flowing; mid-stream retries appear as additional attempt spans.
|
|
1171
|
+
|
|
1172
|
+
See [`examples/telemetry`](./examples/telemetry) for a runnable example that exports to Langfuse.
|
|
1173
|
+
|
|
1095
1174
|
### Streaming
|
|
1096
1175
|
|
|
1097
1176
|
Errors during streaming requests can occur in two ways:
|
|
@@ -1118,6 +1197,7 @@ interface RetryableModelOptions<
|
|
|
1118
1197
|
retries: Array<Retryable<MODEL> | MODEL>;
|
|
1119
1198
|
disabled?: boolean | (() => boolean);
|
|
1120
1199
|
reset?: Reset;
|
|
1200
|
+
experimental_telemetry?: RetryTelemetrySettings;
|
|
1121
1201
|
onError?: (context: RetryContext<MODEL>) => void;
|
|
1122
1202
|
onRetry?: (
|
|
1123
1203
|
context: RetryContext<MODEL>,
|
|
@@ -1132,6 +1212,7 @@ interface RetryableModelOptions<
|
|
|
1132
1212
|
- `retries`: Array of retryables (functions, models, or retry objects) to attempt on failure.
|
|
1133
1213
|
- `disabled`: Disable all retry logic. Can be a boolean or function returning boolean. Default: `false` (retries enabled).
|
|
1134
1214
|
- `reset`: Controls when to reset back to the base model after a successful retry. Default: `after-request`.
|
|
1215
|
+
- `experimental_telemetry`: OpenTelemetry instrumentation for retries. Off by default. See [Telemetry](#telemetry).
|
|
1135
1216
|
- `onError`: Callback invoked when an error occurs.
|
|
1136
1217
|
- `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).
|
|
1137
1218
|
- `onSuccess`: Callback invoked after a successful request. Receives the model that handled the request and all previous attempts.
|