@ai-sdk/anthropic 2.0.79 → 2.0.81

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.
@@ -41,6 +41,12 @@ import {
41
41
  zodSchema as zodSchema2
42
42
  } from "@ai-sdk/provider-utils";
43
43
  import { z as z2 } from "zod/v4";
44
+ var anthropicStopDetailsSchema = z2.object({
45
+ type: z2.string(),
46
+ category: z2.string().nullish(),
47
+ explanation: z2.string().nullish(),
48
+ recommended_model: z2.string().nullish()
49
+ });
44
50
  var anthropicMessagesResponseSchema = lazySchema2(
45
51
  () => zodSchema2(
46
52
  z2.object({
@@ -228,11 +234,18 @@ var anthropicMessagesResponseSchema = lazySchema2(
228
234
  old_start: z2.number().nullable()
229
235
  })
230
236
  ])
237
+ }),
238
+ // Server-side fallback marker. Parsed so the response validates, but
239
+ // dropped from the content output (the AI SDK has no model-hop
240
+ // primitive). The hop remains observable via usage.iterations.
241
+ z2.object({
242
+ type: z2.literal("fallback")
231
243
  })
232
244
  ])
233
245
  ),
234
246
  stop_reason: z2.string().nullish(),
235
247
  stop_sequence: z2.string().nullish(),
248
+ stop_details: anthropicStopDetailsSchema.nullish(),
236
249
  usage: z2.looseObject({
237
250
  input_tokens: z2.number(),
238
251
  output_tokens: z2.number(),
@@ -240,9 +253,17 @@ var anthropicMessagesResponseSchema = lazySchema2(
240
253
  cache_read_input_tokens: z2.number().nullish(),
241
254
  iterations: z2.array(
242
255
  z2.object({
243
- type: z2.union([z2.literal("compaction"), z2.literal("message")]),
256
+ type: z2.union([
257
+ z2.literal("compaction"),
258
+ z2.literal("message"),
259
+ z2.literal("advisor_message"),
260
+ z2.literal("fallback_message")
261
+ ]),
262
+ model: z2.string().nullish(),
244
263
  input_tokens: z2.number(),
245
- output_tokens: z2.number()
264
+ output_tokens: z2.number(),
265
+ cache_creation_input_tokens: z2.number().nullish(),
266
+ cache_read_input_tokens: z2.number().nullish()
246
267
  })
247
268
  ).nullish()
248
269
  }),
@@ -448,6 +469,11 @@ var anthropicMessagesChunkSchema = lazySchema2(
448
469
  old_start: z2.number().nullable()
449
470
  })
450
471
  ])
472
+ }),
473
+ // Server-side fallback marker; dropped from content output (see the
474
+ // response schema). The hop remains observable via usage.iterations.
475
+ z2.object({
476
+ type: z2.literal("fallback")
451
477
  })
452
478
  ])
453
479
  }),
@@ -521,6 +547,7 @@ var anthropicMessagesChunkSchema = lazySchema2(
521
547
  delta: z2.object({
522
548
  stop_reason: z2.string().nullish(),
523
549
  stop_sequence: z2.string().nullish(),
550
+ stop_details: anthropicStopDetailsSchema.nullish(),
524
551
  container: z2.object({
525
552
  expires_at: z2.string(),
526
553
  id: z2.string(),
@@ -543,9 +570,17 @@ var anthropicMessagesChunkSchema = lazySchema2(
543
570
  cache_read_input_tokens: z2.number().nullish(),
544
571
  iterations: z2.array(
545
572
  z2.object({
546
- type: z2.union([z2.literal("compaction"), z2.literal("message")]),
573
+ type: z2.union([
574
+ z2.literal("compaction"),
575
+ z2.literal("message"),
576
+ z2.literal("advisor_message"),
577
+ z2.literal("fallback_message")
578
+ ]),
579
+ model: z2.string().nullish(),
547
580
  input_tokens: z2.number(),
548
- output_tokens: z2.number()
581
+ output_tokens: z2.number(),
582
+ cache_creation_input_tokens: z2.number().nullish(),
583
+ cache_read_input_tokens: z2.number().nullish()
549
584
  })
550
585
  ).nullish()
551
586
  }),
@@ -720,6 +755,31 @@ var anthropicProviderOptions = z3.object({
720
755
  * See https://platform.claude.com/docs/en/build-with-claude/data-residency
721
756
  */
722
757
  inferenceGeo: z3.enum(["us", "global"]).optional(),
758
+ /**
759
+ * Server-side fallback chain.
760
+ *
761
+ * When the primary model's safety classifiers block a turn, the API
762
+ * automatically retries it on the next model in the chain, server-side. A
763
+ * `content-filter` finish reason means the entire chain refused.
764
+ *
765
+ * Each entry is merged into the request as a direct request to that entry's
766
+ * model, so it must be formatted accordingly: `model` is required, and an
767
+ * entry may additionally override `max_tokens`, `thinking`, `output_config`,
768
+ * and `speed` for that attempt only (`speed` additionally requires the speed
769
+ * beta). The value is passed through to the API as-is.
770
+ *
771
+ * The required `server-side-fallback-2026-06-01` beta is added automatically
772
+ * when this option is set.
773
+ */
774
+ fallbacks: z3.array(
775
+ z3.object({
776
+ model: z3.string(),
777
+ max_tokens: z3.number().int().optional(),
778
+ thinking: z3.record(z3.string(), z3.unknown()).optional(),
779
+ output_config: z3.record(z3.string(), z3.unknown()).optional(),
780
+ speed: z3.enum(["fast", "standard"]).optional()
781
+ })
782
+ ).optional(),
723
783
  /**
724
784
  * Context management configuration for automatic context window management.
725
785
  * Enables features like automatic compaction and clearing of tool uses/thinking blocks.
@@ -1418,19 +1478,20 @@ async function convertToAnthropicMessagesPrompt({
1418
1478
  const type = block.type;
1419
1479
  switch (type) {
1420
1480
  case "system": {
1421
- if (system != null) {
1422
- throw new UnsupportedFunctionalityError2({
1423
- functionality: "Multiple system messages that are separated by user/assistant messages"
1424
- });
1425
- }
1426
- system = block.messages.map(({ content, providerOptions }) => ({
1481
+ const content = block.messages.map(({ content: content2, providerOptions }) => ({
1427
1482
  type: "text",
1428
- text: content,
1483
+ text: content2,
1429
1484
  cache_control: validator.getCacheControl(providerOptions, {
1430
1485
  type: "system message",
1431
1486
  canCache: true
1432
1487
  })
1433
1488
  }));
1489
+ if (system == null) {
1490
+ system = content;
1491
+ } else {
1492
+ messages.push({ role: "system", content });
1493
+ betas.add("mid-conversation-system-2026-04-07");
1494
+ }
1434
1495
  break;
1435
1496
  }
1436
1497
  case "user": {
@@ -2307,6 +2368,9 @@ var AnthropicMessagesLanguageModel = class {
2307
2368
  ...(anthropicOptions == null ? void 0 : anthropicOptions.inferenceGeo) && {
2308
2369
  inference_geo: anthropicOptions.inferenceGeo
2309
2370
  },
2371
+ ...(anthropicOptions == null ? void 0 : anthropicOptions.fallbacks) && anthropicOptions.fallbacks.length > 0 && {
2372
+ fallbacks: anthropicOptions.fallbacks
2373
+ },
2310
2374
  ...(anthropicOptions == null ? void 0 : anthropicOptions.cacheControl) && {
2311
2375
  cache_control: anthropicOptions.cacheControl
2312
2376
  },
@@ -2449,6 +2513,9 @@ var AnthropicMessagesLanguageModel = class {
2449
2513
  if ((anthropicOptions == null ? void 0 : anthropicOptions.speed) === "fast") {
2450
2514
  betas.add("fast-mode-2026-02-01");
2451
2515
  }
2516
+ if ((anthropicOptions == null ? void 0 : anthropicOptions.fallbacks) && anthropicOptions.fallbacks.length > 0) {
2517
+ betas.add("server-side-fallback-2026-06-01");
2518
+ }
2452
2519
  if (useStructuredOutput) {
2453
2520
  betas.add("structured-outputs-2025-11-13");
2454
2521
  }
@@ -2548,7 +2615,7 @@ var AnthropicMessagesLanguageModel = class {
2548
2615
  });
2549
2616
  }
2550
2617
  async doGenerate(options) {
2551
- var _a, _b, _c, _d, _e, _f, _g, _h;
2618
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2552
2619
  const { args, warnings, betas, usesJsonResponseTool } = await this.getArgs({
2553
2620
  ...options,
2554
2621
  userSuppliedBetas: await this.getBetasFromHeaders(options.headers)
@@ -2788,11 +2855,20 @@ var AnthropicMessagesLanguageModel = class {
2788
2855
  });
2789
2856
  break;
2790
2857
  }
2858
+ // Server-side fallback marker: the AI SDK has no content primitive for
2859
+ // a model hop, so drop it. The hop is still observable via
2860
+ // usage.iterations.
2861
+ case "fallback": {
2862
+ break;
2863
+ }
2791
2864
  }
2792
2865
  }
2793
2866
  let inputTokens;
2794
2867
  let outputTokens;
2795
- if (response.usage.iterations && response.usage.iterations.length > 0) {
2868
+ const servedByFallback = (_b = response.usage.iterations) == null ? void 0 : _b.some(
2869
+ (iter) => iter.type === "fallback_message"
2870
+ );
2871
+ if (response.usage.iterations && response.usage.iterations.length > 0 && !servedByFallback) {
2796
2872
  const totals = response.usage.iterations.reduce(
2797
2873
  (acc, iter) => ({
2798
2874
  input: acc.input + iter.input_tokens,
@@ -2806,6 +2882,7 @@ var AnthropicMessagesLanguageModel = class {
2806
2882
  inputTokens = response.usage.input_tokens;
2807
2883
  outputTokens = response.usage.output_tokens;
2808
2884
  }
2885
+ const stopDetails = mapAnthropicStopDetails(response.stop_details);
2809
2886
  return {
2810
2887
  content,
2811
2888
  finishReason: mapAnthropicStopReason({
@@ -2816,12 +2893,12 @@ var AnthropicMessagesLanguageModel = class {
2816
2893
  inputTokens,
2817
2894
  outputTokens,
2818
2895
  totalTokens: inputTokens + outputTokens,
2819
- cachedInputTokens: (_b = response.usage.cache_read_input_tokens) != null ? _b : void 0
2896
+ cachedInputTokens: (_c = response.usage.cache_read_input_tokens) != null ? _c : void 0
2820
2897
  },
2821
2898
  request: { body: args },
2822
2899
  response: {
2823
- id: (_c = response.id) != null ? _c : void 0,
2824
- modelId: (_d = response.model) != null ? _d : void 0,
2900
+ id: (_d = response.id) != null ? _d : void 0,
2901
+ modelId: (_e = response.model) != null ? _e : void 0,
2825
2902
  headers: responseHeaders,
2826
2903
  body: rawResponse
2827
2904
  },
@@ -2829,21 +2906,23 @@ var AnthropicMessagesLanguageModel = class {
2829
2906
  providerMetadata: {
2830
2907
  anthropic: {
2831
2908
  usage: response.usage,
2832
- cacheCreationInputTokens: (_e = response.usage.cache_creation_input_tokens) != null ? _e : null,
2833
- stopSequence: (_f = response.stop_sequence) != null ? _f : null,
2909
+ cacheCreationInputTokens: (_f = response.usage.cache_creation_input_tokens) != null ? _f : null,
2910
+ stopSequence: (_g = response.stop_sequence) != null ? _g : null,
2911
+ ...stopDetails != null ? { stopDetails } : {},
2834
2912
  iterations: response.usage.iterations ? response.usage.iterations.map((iter) => ({
2835
2913
  type: iter.type,
2914
+ ...iter.model != null ? { model: iter.model } : {},
2836
2915
  inputTokens: iter.input_tokens,
2837
2916
  outputTokens: iter.output_tokens
2838
2917
  })) : null,
2839
2918
  container: response.container ? {
2840
2919
  expiresAt: response.container.expires_at,
2841
2920
  id: response.container.id,
2842
- skills: (_h = (_g = response.container.skills) == null ? void 0 : _g.map((skill) => ({
2921
+ skills: (_i = (_h = response.container.skills) == null ? void 0 : _h.map((skill) => ({
2843
2922
  type: skill.type,
2844
2923
  skillId: skill.skill_id,
2845
2924
  version: skill.version
2846
- }))) != null ? _h : null
2925
+ }))) != null ? _i : null
2847
2926
  } : null,
2848
2927
  contextManagement: response.context_management ? {
2849
2928
  appliedEdits: response.context_management.applied_edits.map(
@@ -2904,6 +2983,7 @@ var AnthropicMessagesLanguageModel = class {
2904
2983
  let rawUsage = void 0;
2905
2984
  let cacheCreationInputTokens = null;
2906
2985
  let stopSequence = null;
2986
+ let stopDetails = void 0;
2907
2987
  let container = null;
2908
2988
  let iterations = null;
2909
2989
  let contextManagement = null;
@@ -2915,7 +2995,7 @@ var AnthropicMessagesLanguageModel = class {
2915
2995
  controller.enqueue({ type: "stream-start", warnings });
2916
2996
  },
2917
2997
  transform(chunk, controller) {
2918
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
2998
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2919
2999
  if (options.includeRawChunks) {
2920
3000
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
2921
3001
  }
@@ -2930,6 +3010,9 @@ var AnthropicMessagesLanguageModel = class {
2930
3010
  }
2931
3011
  case "content_block_start": {
2932
3012
  const contentBlockType = value.content_block.type;
3013
+ if (contentBlockType === "fallback") {
3014
+ return;
3015
+ }
2933
3016
  blockType = contentBlockType;
2934
3017
  switch (contentBlockType) {
2935
3018
  case "text": {
@@ -3322,7 +3405,10 @@ var AnthropicMessagesLanguageModel = class {
3322
3405
  if (value.usage.iterations != null) {
3323
3406
  iterations = value.usage.iterations;
3324
3407
  }
3325
- if (value.usage.iterations && value.usage.iterations.length > 0) {
3408
+ const servedByFallback = (_f = value.usage.iterations) == null ? void 0 : _f.some(
3409
+ (iter) => iter.type === "fallback_message"
3410
+ );
3411
+ if (value.usage.iterations && value.usage.iterations.length > 0 && !servedByFallback) {
3326
3412
  const totals = value.usage.iterations.reduce(
3327
3413
  (acc, iter) => ({
3328
3414
  input: acc.input + iter.input_tokens,
@@ -3338,20 +3424,21 @@ var AnthropicMessagesLanguageModel = class {
3338
3424
  }
3339
3425
  usage.outputTokens = value.usage.output_tokens;
3340
3426
  }
3341
- usage.totalTokens = ((_f = usage.inputTokens) != null ? _f : 0) + ((_g = usage.outputTokens) != null ? _g : 0);
3427
+ usage.totalTokens = ((_g = usage.inputTokens) != null ? _g : 0) + ((_h = usage.outputTokens) != null ? _h : 0);
3342
3428
  finishReason = mapAnthropicStopReason({
3343
3429
  finishReason: value.delta.stop_reason,
3344
3430
  isJsonResponseFromTool: usesJsonResponseTool
3345
3431
  });
3346
- stopSequence = (_h = value.delta.stop_sequence) != null ? _h : null;
3432
+ stopDetails = mapAnthropicStopDetails(value.delta.stop_details);
3433
+ stopSequence = (_i = value.delta.stop_sequence) != null ? _i : null;
3347
3434
  container = value.delta.container != null ? {
3348
3435
  expiresAt: value.delta.container.expires_at,
3349
3436
  id: value.delta.container.id,
3350
- skills: (_j = (_i = value.delta.container.skills) == null ? void 0 : _i.map((skill) => ({
3437
+ skills: (_k = (_j = value.delta.container.skills) == null ? void 0 : _j.map((skill) => ({
3351
3438
  type: skill.type,
3352
3439
  skillId: skill.skill_id,
3353
3440
  version: skill.version
3354
- }))) != null ? _j : null
3441
+ }))) != null ? _k : null
3355
3442
  } : null;
3356
3443
  if (value.context_management != null) {
3357
3444
  contextManagement = {
@@ -3396,8 +3483,10 @@ var AnthropicMessagesLanguageModel = class {
3396
3483
  usage: rawUsage != null ? rawUsage : null,
3397
3484
  cacheCreationInputTokens,
3398
3485
  stopSequence,
3486
+ ...stopDetails != null ? { stopDetails } : {},
3399
3487
  iterations: iterations ? iterations.map((iter) => ({
3400
3488
  type: iter.type,
3489
+ ...iter.model != null ? { model: iter.model } : {},
3401
3490
  inputTokens: iter.input_tokens,
3402
3491
  outputTokens: iter.output_tokens
3403
3492
  })) : null,
@@ -3453,7 +3542,7 @@ var AnthropicMessagesLanguageModel = class {
3453
3542
  }
3454
3543
  };
3455
3544
  function getModelCapabilities(modelId) {
3456
- if (modelId.includes("claude-opus-4-7")) {
3545
+ if (modelId.includes("claude-opus-4-8") || modelId.includes("claude-opus-4-7") || modelId.includes("claude-fable-5")) {
3457
3546
  return {
3458
3547
  maxOutputTokens: 128e3,
3459
3548
  supportsStructuredOutput: true,
@@ -3518,6 +3607,17 @@ function getModelCapabilities(modelId) {
3518
3607
  };
3519
3608
  }
3520
3609
  }
3610
+ function mapAnthropicStopDetails(stopDetails) {
3611
+ if (stopDetails == null) {
3612
+ return void 0;
3613
+ }
3614
+ return {
3615
+ type: stopDetails.type,
3616
+ ...stopDetails.category != null ? { category: stopDetails.category } : {},
3617
+ ...stopDetails.explanation != null ? { explanation: stopDetails.explanation } : {},
3618
+ ...stopDetails.recommended_model != null ? { recommendedModel: stopDetails.recommended_model } : {}
3619
+ };
3620
+ }
3521
3621
 
3522
3622
  // src/tool/bash_20241022.ts
3523
3623
  import {