@ai-sdk/anthropic 3.0.81 → 3.0.82

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.
@@ -293,6 +293,63 @@ const { text } = await generateText({
293
293
 
294
294
  The `inferenceGeo` option accepts `'us'` (US-only infrastructure) or `'global'` (default, any available geography).
295
295
 
296
+ ### Safety Classifiers and Fallbacks
297
+
298
+ Claude Fable 5 has safeguards that limit its performance in certain areas like cybersecurity, biology, and chemistry, and automated safety checks are run on every request.
299
+
300
+ When one of these checks blocks a request, the API does not answer it. Instead it returns a classifier block: a `200` response with a `refusal` stop reason and an optional `stop_details` object describing the category that triggered the block. The AI SDK surfaces this as a `content-filter` finish reason, with the details available on `providerMetadata.anthropic.stopDetails`.
301
+
302
+ A classifier block looks like this:
303
+
304
+ ```json
305
+ {
306
+ "type": "message",
307
+ "model": "claude-fable-5",
308
+ "content": [],
309
+ "stop_reason": "refusal",
310
+ "stop_details": {
311
+ "type": "refusal",
312
+ "category": "cyber",
313
+ "explanation": "This request triggered restrictions on violative cyber content and was blocked under Anthropic's Usage Policy."
314
+ }
315
+ }
316
+ ```
317
+
318
+ Branch on the finish reason rather than on the presence of `stop_details` — the API may return a refusal with no details at all.
319
+
320
+ To avoid receiving a classifier block, pass the `fallbacks` option. When the primary model's classifiers block a turn, the API automatically retries it server-side on the next model in the chain and returns that model's answer. The required beta header is added for you.
321
+
322
+ ```ts highlight="8-10"
323
+ import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
324
+ import { generateText } from 'ai';
325
+
326
+ const { text } = await generateText({
327
+ model: anthropic('claude-fable-5'),
328
+ prompt: 'Explain the history of cryptography.',
329
+ providerOptions: {
330
+ anthropic: {
331
+ fallbacks: [{ model: 'claude-fable-5' }],
332
+ } satisfies AnthropicLanguageModelOptions,
333
+ },
334
+ });
335
+ ```
336
+
337
+ Each fallback entry requires a `model` and may additionally override `max_tokens`, `thinking`, `output_config`, and `speed` for that attempt only.
338
+
339
+ When a fallback serves the turn, it is recorded in the per-model usage breakdown (`usage.iterations`) as a `fallback_message` entry. The AI SDK exposes this breakdown on `providerMetadata.anthropic.iterations`, so you can detect whether a fallback ran:
340
+
341
+ ```ts
342
+ // set up `result` with a `streamText` call passing `fallbacks` as shown
343
+ // above, then consume the stream
344
+
345
+ const { iterations } = (await result.providerMetadata)?.anthropic ?? {};
346
+ const servedByFallback = iterations?.some(
347
+ iteration => iteration.type === 'fallback_message',
348
+ );
349
+
350
+ console.log('Served by fallback:', servedByFallback);
351
+ ```
352
+
296
353
  ### Reasoning
297
354
 
298
355
  Anthropic models support extended thinking, where Claude shows its reasoning process before providing a final answer.
@@ -1502,6 +1559,7 @@ and the `mediaType` should be set to `'application/pdf'`.
1502
1559
 
1503
1560
  | Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
1504
1561
  | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
1562
+ | `claude-fable-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
1505
1563
  | `claude-opus-4-8` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
1506
1564
  | `claude-opus-4-7` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
1507
1565
  | `claude-opus-4-6` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/anthropic",
3
- "version": "3.0.81",
3
+ "version": "3.0.82",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -8,66 +8,43 @@ import type { JSONObject } from '@ai-sdk/provider';
8
8
  * - `compaction`: a context compaction step (billed at executor rates).
9
9
  * - `message`: an executor sampling iteration (billed at executor rates).
10
10
  * - `advisor_message`: an advisor sub-inference (billed at the advisor
11
- * model's rates; `model` carries the advisor model ID). Advisor token
12
- * usage is NOT rolled into the top-level usage totals because it bills
13
- * at a different rate; inspect this array directly for advisor billing.
11
+ * model's rates). Advisor token usage is NOT rolled into the top-level
12
+ * usage totals because it bills at a different rate; inspect this array
13
+ * directly for advisor billing.
14
+ * - `fallback_message`: a server-side fallback attempt that served the turn.
15
+ * Inspect this array for exact per-model attribution on a turn that fell
16
+ * back.
14
17
  */
15
- export type AnthropicUsageIteration =
16
- | {
17
- type: 'compaction' | 'message';
18
+ export type AnthropicUsageIteration = {
19
+ type: 'compaction' | 'message' | 'advisor_message' | 'fallback_message';
18
20
 
19
- /**
20
- * Number of input tokens consumed in this iteration.
21
- */
22
- inputTokens: number;
23
-
24
- /**
25
- * Number of output tokens generated in this iteration.
26
- */
27
- outputTokens: number;
28
-
29
- /**
30
- * Number of cache-creation input tokens consumed in this iteration.
31
- */
32
- cacheCreationInputTokens?: number;
33
-
34
- /**
35
- * Number of cache-read input tokens consumed in this iteration.
36
- */
37
- cacheReadInputTokens?: number;
38
- }
39
- | {
40
- type: 'advisor_message';
41
-
42
- /**
43
- * The advisor model that produced this iteration.
44
- */
45
- model: string;
21
+ /**
22
+ * The model that produced this iteration. Populated for the per-model
23
+ * attribution cases (the fallback chain and advisor sub-inferences) and
24
+ * absent otherwise.
25
+ */
26
+ model?: string;
46
27
 
47
- /**
48
- * Number of input tokens consumed in this iteration.
49
- */
50
- inputTokens: number;
28
+ /**
29
+ * Number of input tokens consumed in this iteration.
30
+ */
31
+ inputTokens: number;
51
32
 
52
- /**
53
- * Number of output tokens generated in this iteration.
54
- */
55
- outputTokens: number;
33
+ /**
34
+ * Number of output tokens generated in this iteration.
35
+ */
36
+ outputTokens: number;
56
37
 
57
- /**
58
- * Number of cache-creation input tokens consumed by this advisor
59
- * sub-inference. Nonzero when advisor-side caching is enabled and
60
- * the advisor writes a fresh cache entry.
61
- */
62
- cacheCreationInputTokens?: number;
38
+ /**
39
+ * Number of cache-creation input tokens consumed in this iteration.
40
+ */
41
+ cacheCreationInputTokens?: number;
63
42
 
64
- /**
65
- * Number of cache-read input tokens consumed by this advisor
66
- * sub-inference. Nonzero on the second and later advisor calls
67
- * when advisor-side caching is enabled.
68
- */
69
- cacheReadInputTokens?: number;
70
- };
43
+ /**
44
+ * Number of cache-read input tokens consumed in this iteration.
45
+ */
46
+ cacheReadInputTokens?: number;
47
+ };
71
48
 
72
49
  export interface AnthropicMessageMetadata {
73
50
  usage: JSONObject;
@@ -76,6 +53,42 @@ export interface AnthropicMessageMetadata {
76
53
  cacheCreationInputTokens: number | null;
77
54
  stopSequence: string | null;
78
55
 
56
+ /**
57
+ * Details about why the request stopped. Present only when the API returns
58
+ * a `refusal` stop reason together with a `stop_details` object (a
59
+ * classifier block or a model refusal).
60
+ *
61
+ * Branch on the finish reason (`content-filter`), not on this object: the
62
+ * API may return a refusal with no details at all, so this field can be
63
+ * absent even on a refusal and should not be relied upon being present.
64
+ */
65
+ stopDetails?: {
66
+ /**
67
+ * The kind of stop detail. `'refusal'` for classifier blocks and model
68
+ * refusals.
69
+ */
70
+ type: string;
71
+
72
+ /**
73
+ * The classifier category that triggered the block, e.g. `'cyber'` or
74
+ * `'bio'`. Absent for model refusals and other cases.
75
+ */
76
+ category?: string;
77
+
78
+ /**
79
+ * Human-readable explanation of why the request was blocked. May be
80
+ * absent even on a refusal.
81
+ */
82
+ explanation?: string;
83
+
84
+ /**
85
+ * The canonical id of a model to retry directly. Populated only when the
86
+ * request included fallbacks and the fallback attempt could not be made
87
+ * (e.g. the fallback model was rate limited or overloaded).
88
+ */
89
+ recommendedModel?: string;
90
+ };
91
+
79
92
  /**
80
93
  * Usage breakdown by iteration when compaction is triggered.
81
94
  *
@@ -601,6 +601,15 @@ export type AnthropicResponseContextManagement = {
601
601
  applied_edits: AnthropicResponseContextManagementEdit[];
602
602
  };
603
603
 
604
+ const anthropicStopDetailsSchema = z.object({
605
+ type: z.string(),
606
+ category: z.string().nullish(),
607
+ explanation: z.string().nullish(),
608
+ recommended_model: z.string().nullish(),
609
+ });
610
+
611
+ export type AnthropicStopDetails = z.infer<typeof anthropicStopDetailsSchema>;
612
+
604
613
  // limited version of the schema, focussed on what is needed for the implementation
605
614
  // this approach limits breakages when the API changes and increases efficiency
606
615
  export const anthropicMessagesResponseSchema = lazySchema(() =>
@@ -901,10 +910,17 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
901
910
  }),
902
911
  ]),
903
912
  }),
913
+ // Server-side fallback marker. Parsed so the response validates, but
914
+ // dropped from the content output (the AI SDK has no model-hop
915
+ // primitive). The hop remains observable via usage.iterations.
916
+ z.object({
917
+ type: z.literal('fallback'),
918
+ }),
904
919
  ]),
905
920
  ),
906
921
  stop_reason: z.string().nullish(),
907
922
  stop_sequence: z.string().nullish(),
923
+ stop_details: anthropicStopDetailsSchema.nullish(),
908
924
  usage: z.looseObject({
909
925
  input_tokens: z.number(),
910
926
  output_tokens: z.number(),
@@ -912,23 +928,19 @@ export const anthropicMessagesResponseSchema = lazySchema(() =>
912
928
  cache_read_input_tokens: z.number().nullish(),
913
929
  iterations: z
914
930
  .array(
915
- z.union([
916
- z.object({
917
- type: z.union([z.literal('compaction'), z.literal('message')]),
918
- input_tokens: z.number(),
919
- output_tokens: z.number(),
920
- cache_creation_input_tokens: z.number().nullish(),
921
- cache_read_input_tokens: z.number().nullish(),
922
- }),
923
- z.object({
924
- type: z.literal('advisor_message'),
925
- model: z.string(),
926
- input_tokens: z.number(),
927
- output_tokens: z.number(),
928
- cache_creation_input_tokens: z.number().nullish(),
929
- cache_read_input_tokens: z.number().nullish(),
930
- }),
931
- ]),
931
+ z.object({
932
+ type: z.union([
933
+ z.literal('compaction'),
934
+ z.literal('message'),
935
+ z.literal('advisor_message'),
936
+ z.literal('fallback_message'),
937
+ ]),
938
+ model: z.string().nullish(),
939
+ input_tokens: z.number(),
940
+ output_tokens: z.number(),
941
+ cache_creation_input_tokens: z.number().nullish(),
942
+ cache_read_input_tokens: z.number().nullish(),
943
+ }),
932
944
  )
933
945
  .nullish(),
934
946
  }),
@@ -1290,6 +1302,11 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
1290
1302
  }),
1291
1303
  ]),
1292
1304
  }),
1305
+ // Server-side fallback marker; dropped from content output (see the
1306
+ // response schema). The hop remains observable via usage.iterations.
1307
+ z.object({
1308
+ type: z.literal('fallback'),
1309
+ }),
1293
1310
  ]),
1294
1311
  }),
1295
1312
  z.object({
@@ -1362,6 +1379,7 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
1362
1379
  delta: z.object({
1363
1380
  stop_reason: z.string().nullish(),
1364
1381
  stop_sequence: z.string().nullish(),
1382
+ stop_details: anthropicStopDetailsSchema.nullish(),
1365
1383
  container: z
1366
1384
  .object({
1367
1385
  expires_at: z.string(),
@@ -1388,26 +1406,19 @@ export const anthropicMessagesChunkSchema = lazySchema(() =>
1388
1406
  cache_read_input_tokens: z.number().nullish(),
1389
1407
  iterations: z
1390
1408
  .array(
1391
- z.union([
1392
- z.object({
1393
- type: z.union([
1394
- z.literal('compaction'),
1395
- z.literal('message'),
1396
- ]),
1397
- input_tokens: z.number(),
1398
- output_tokens: z.number(),
1399
- cache_creation_input_tokens: z.number().nullish(),
1400
- cache_read_input_tokens: z.number().nullish(),
1401
- }),
1402
- z.object({
1403
- type: z.literal('advisor_message'),
1404
- model: z.string(),
1405
- input_tokens: z.number(),
1406
- output_tokens: z.number(),
1407
- cache_creation_input_tokens: z.number().nullish(),
1408
- cache_read_input_tokens: z.number().nullish(),
1409
- }),
1410
- ]),
1409
+ z.object({
1410
+ type: z.union([
1411
+ z.literal('compaction'),
1412
+ z.literal('message'),
1413
+ z.literal('advisor_message'),
1414
+ z.literal('fallback_message'),
1415
+ ]),
1416
+ model: z.string().nullish(),
1417
+ input_tokens: z.number(),
1418
+ output_tokens: z.number(),
1419
+ cache_creation_input_tokens: z.number().nullish(),
1420
+ cache_read_input_tokens: z.number().nullish(),
1421
+ }),
1411
1422
  )
1412
1423
  .nullish(),
1413
1424
  }),
@@ -40,6 +40,7 @@ import {
40
40
  type AnthropicContainer,
41
41
  type AnthropicReasoningMetadata,
42
42
  type AnthropicResponseContextManagement,
43
+ type AnthropicStopDetails,
43
44
  type AnthropicTool,
44
45
  type Citation,
45
46
  } from './anthropic-messages-api';
@@ -438,6 +439,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
438
439
  ...(anthropicOptions?.inferenceGeo && {
439
440
  inference_geo: anthropicOptions.inferenceGeo,
440
441
  }),
442
+ ...(anthropicOptions?.fallbacks &&
443
+ anthropicOptions.fallbacks.length > 0 && {
444
+ fallbacks: anthropicOptions.fallbacks,
445
+ }),
441
446
  ...(anthropicOptions?.cacheControl && {
442
447
  cache_control: anthropicOptions.cacheControl,
443
448
  }),
@@ -664,6 +669,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
664
669
  betas.add('fast-mode-2026-02-01');
665
670
  }
666
671
 
672
+ if (anthropicOptions?.fallbacks && anthropicOptions.fallbacks.length > 0) {
673
+ betas.add('server-side-fallback-2026-06-01');
674
+ }
675
+
667
676
  const defaultEagerInputStreaming =
668
677
  stream && (anthropicOptions?.toolStreaming ?? true);
669
678
 
@@ -1281,6 +1290,13 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1281
1290
  }
1282
1291
  break;
1283
1292
  }
1293
+
1294
+ // Server-side fallback marker: the AI SDK has no content primitive for
1295
+ // a model hop, so drop it. The hop is still observable via
1296
+ // usage.iterations.
1297
+ case 'fallback': {
1298
+ break;
1299
+ }
1284
1300
  }
1285
1301
  }
1286
1302
 
@@ -1303,48 +1319,35 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1303
1319
  },
1304
1320
  warnings,
1305
1321
  providerMetadata: (() => {
1322
+ const stopDetails = mapAnthropicStopDetails(response.stop_details);
1323
+
1306
1324
  const anthropicMetadata = {
1307
1325
  usage: response.usage as JSONObject,
1308
1326
  cacheCreationInputTokens:
1309
1327
  response.usage.cache_creation_input_tokens ?? null,
1310
1328
  stopSequence: response.stop_sequence ?? null,
1329
+ ...(stopDetails != null ? { stopDetails } : {}),
1311
1330
 
1312
1331
  iterations: response.usage.iterations
1313
- ? response.usage.iterations.map(iter =>
1314
- iter.type === 'advisor_message'
1315
- ? ({
1316
- type: iter.type,
1317
- model: iter.model,
1318
- inputTokens: iter.input_tokens,
1319
- outputTokens: iter.output_tokens,
1320
- ...(iter.cache_creation_input_tokens
1321
- ? {
1322
- cacheCreationInputTokens:
1323
- iter.cache_creation_input_tokens,
1324
- }
1325
- : {}),
1326
- ...(iter.cache_read_input_tokens
1327
- ? {
1328
- cacheReadInputTokens: iter.cache_read_input_tokens,
1329
- }
1330
- : {}),
1331
- } satisfies AnthropicUsageIteration)
1332
- : ({
1333
- type: iter.type,
1334
- inputTokens: iter.input_tokens,
1335
- outputTokens: iter.output_tokens,
1336
- ...(iter.cache_creation_input_tokens
1337
- ? {
1338
- cacheCreationInputTokens:
1339
- iter.cache_creation_input_tokens,
1340
- }
1341
- : {}),
1342
- ...(iter.cache_read_input_tokens
1343
- ? {
1344
- cacheReadInputTokens: iter.cache_read_input_tokens,
1345
- }
1346
- : {}),
1347
- } satisfies AnthropicUsageIteration),
1332
+ ? response.usage.iterations.map(
1333
+ iter =>
1334
+ ({
1335
+ type: iter.type,
1336
+ ...(iter.model != null ? { model: iter.model } : {}),
1337
+ inputTokens: iter.input_tokens,
1338
+ outputTokens: iter.output_tokens,
1339
+ ...(iter.cache_creation_input_tokens
1340
+ ? {
1341
+ cacheCreationInputTokens:
1342
+ iter.cache_creation_input_tokens,
1343
+ }
1344
+ : {}),
1345
+ ...(iter.cache_read_input_tokens
1346
+ ? {
1347
+ cacheReadInputTokens: iter.cache_read_input_tokens,
1348
+ }
1349
+ : {}),
1350
+ }) satisfies AnthropicUsageIteration,
1348
1351
  )
1349
1352
  : null,
1350
1353
  container: response.container
@@ -1458,6 +1461,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1458
1461
  let rawUsage: JSONObject | undefined = undefined;
1459
1462
  let cacheCreationInputTokens: number | null = null;
1460
1463
  let stopSequence: string | null = null;
1464
+ let stopDetails: AnthropicMessageMetadata['stopDetails'] = undefined;
1461
1465
  let container: AnthropicMessageMetadata['container'] | null = null;
1462
1466
  let isJsonResponseFromTool = false;
1463
1467
 
@@ -1510,6 +1514,14 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1510
1514
  case 'content_block_start': {
1511
1515
  const part = value.content_block;
1512
1516
  const contentBlockType = part.type;
1517
+
1518
+ // Server-side fallback marker: the AI SDK has no content
1519
+ // primitive for a model hop, so drop it. The hop is still
1520
+ // observable via usage.iterations.
1521
+ if (contentBlockType === 'fallback') {
1522
+ return;
1523
+ }
1524
+
1513
1525
  blockType = contentBlockType;
1514
1526
 
1515
1527
  switch (contentBlockType) {
@@ -2362,6 +2374,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
2362
2374
  };
2363
2375
 
2364
2376
  stopSequence = value.delta.stop_sequence ?? null;
2377
+ stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
2365
2378
  container =
2366
2379
  value.delta.container != null
2367
2380
  ? {
@@ -2395,44 +2408,28 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
2395
2408
  usage: (rawUsage as JSONObject) ?? null,
2396
2409
  cacheCreationInputTokens,
2397
2410
  stopSequence,
2411
+ ...(stopDetails != null ? { stopDetails } : {}),
2398
2412
  iterations: usage.iterations
2399
- ? usage.iterations.map(iter =>
2400
- iter.type === 'advisor_message'
2401
- ? ({
2402
- type: iter.type,
2403
- model: iter.model,
2404
- inputTokens: iter.input_tokens,
2405
- outputTokens: iter.output_tokens,
2406
- ...(iter.cache_creation_input_tokens
2407
- ? {
2408
- cacheCreationInputTokens:
2409
- iter.cache_creation_input_tokens,
2410
- }
2411
- : {}),
2412
- ...(iter.cache_read_input_tokens
2413
- ? {
2414
- cacheReadInputTokens:
2415
- iter.cache_read_input_tokens,
2416
- }
2417
- : {}),
2418
- } satisfies AnthropicUsageIteration)
2419
- : ({
2420
- type: iter.type,
2421
- inputTokens: iter.input_tokens,
2422
- outputTokens: iter.output_tokens,
2423
- ...(iter.cache_creation_input_tokens
2424
- ? {
2425
- cacheCreationInputTokens:
2426
- iter.cache_creation_input_tokens,
2427
- }
2428
- : {}),
2429
- ...(iter.cache_read_input_tokens
2430
- ? {
2431
- cacheReadInputTokens:
2432
- iter.cache_read_input_tokens,
2433
- }
2434
- : {}),
2435
- } satisfies AnthropicUsageIteration),
2413
+ ? usage.iterations.map(
2414
+ iter =>
2415
+ ({
2416
+ type: iter.type,
2417
+ ...(iter.model != null ? { model: iter.model } : {}),
2418
+ inputTokens: iter.input_tokens,
2419
+ outputTokens: iter.output_tokens,
2420
+ ...(iter.cache_creation_input_tokens
2421
+ ? {
2422
+ cacheCreationInputTokens:
2423
+ iter.cache_creation_input_tokens,
2424
+ }
2425
+ : {}),
2426
+ ...(iter.cache_read_input_tokens
2427
+ ? {
2428
+ cacheReadInputTokens:
2429
+ iter.cache_read_input_tokens,
2430
+ }
2431
+ : {}),
2432
+ }) satisfies AnthropicUsageIteration,
2436
2433
  )
2437
2434
  : null,
2438
2435
  container,
@@ -2530,7 +2527,8 @@ function getModelCapabilities(modelId: string): {
2530
2527
  } {
2531
2528
  if (
2532
2529
  modelId.includes('claude-opus-4-8') ||
2533
- modelId.includes('claude-opus-4-7')
2530
+ modelId.includes('claude-opus-4-7') ||
2531
+ modelId.includes('claude-fable-5')
2534
2532
  ) {
2535
2533
  return {
2536
2534
  maxOutputTokens: 128000,
@@ -2656,3 +2654,22 @@ function mapAnthropicResponseContextManagement(
2656
2654
  }
2657
2655
  : null;
2658
2656
  }
2657
+
2658
+ function mapAnthropicStopDetails(
2659
+ stopDetails: AnthropicStopDetails | null | undefined,
2660
+ ): AnthropicMessageMetadata['stopDetails'] | undefined {
2661
+ if (stopDetails == null) {
2662
+ return undefined;
2663
+ }
2664
+
2665
+ return {
2666
+ type: stopDetails.type,
2667
+ ...(stopDetails.category != null ? { category: stopDetails.category } : {}),
2668
+ ...(stopDetails.explanation != null
2669
+ ? { explanation: stopDetails.explanation }
2670
+ : {}),
2671
+ ...(stopDetails.recommended_model != null
2672
+ ? { recommendedModel: stopDetails.recommended_model }
2673
+ : {}),
2674
+ };
2675
+ }
@@ -19,6 +19,7 @@ export type AnthropicMessagesModelId =
19
19
  | 'claude-opus-4-6'
20
20
  | 'claude-opus-4-7'
21
21
  | 'claude-opus-4-8'
22
+ | 'claude-fable-5'
22
23
  | (string & {});
23
24
 
24
25
  /**
@@ -224,6 +225,34 @@ export const anthropicLanguageModelOptions = z.object({
224
225
  */
225
226
  inferenceGeo: z.enum(['us', 'global']).optional(),
226
227
 
228
+ /**
229
+ * Server-side fallback chain.
230
+ *
231
+ * When the primary model's safety classifiers block a turn, the API
232
+ * automatically retries it on the next model in the chain, server-side. A
233
+ * `content-filter` finish reason means the entire chain refused.
234
+ *
235
+ * Each entry is merged into the request as a direct request to that entry's
236
+ * model, so it must be formatted accordingly: `model` is required, and an
237
+ * entry may additionally override `max_tokens`, `thinking`, `output_config`,
238
+ * and `speed` for that attempt only (`speed` additionally requires the speed
239
+ * beta). The value is passed through to the API as-is.
240
+ *
241
+ * The required `server-side-fallback-2026-06-01` beta is added automatically
242
+ * when this option is set.
243
+ */
244
+ fallbacks: z
245
+ .array(
246
+ z.object({
247
+ model: z.string(),
248
+ max_tokens: z.number().int().optional(),
249
+ thinking: z.record(z.string(), z.unknown()).optional(),
250
+ output_config: z.record(z.string(), z.unknown()).optional(),
251
+ speed: z.enum(['fast', 'standard']).optional(),
252
+ }),
253
+ )
254
+ .optional(),
255
+
227
256
  /**
228
257
  * A set of beta features to enable.
229
258
  * Allow a provider to receive the full `betas` set if it needs it.