@ai-sdk/anthropic 3.0.127 → 3.0.129

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.
@@ -200,9 +200,18 @@ verify that a tool call was made.
200
200
 
201
201
  ### Effort
202
202
 
203
- Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5`, `claude-opus-5-5`, `claude-fable-5`, `claude-fable-5-1`, `claude-sonnet-5`, and `claude-sonnet-5-5` additionally support `xhigh` for maximum reasoning effort.
203
+ Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5`, `claude-opus-5-5`, `claude-fable-5`, `claude-fable-5-1`, `claude-sonnet-5`, `claude-sonnet-5-5`, and `claude-haiku-5-5` additionally support `xhigh` for maximum reasoning effort.
204
204
 
205
- On `claude-opus-5`, thinking can only be disabled at effort levels up to and including `high`. When you combine `thinking: { type: 'disabled' }` with `effort: 'xhigh'` or `effort: 'max'`, the AI SDK lowers the effort to `high` and emits a warning instead of sending a request that the API would reject.
205
+ On `claude-opus-5` and `claude-haiku-5-5`, thinking can only be disabled at effort levels up to and including `high`. When you combine `thinking: { type: 'disabled' }` with `effort: 'xhigh'` or `effort: 'max'`, the AI SDK lowers the effort to `high` and emits a warning instead of sending a request that the API would reject.
206
+
207
+ `claude-haiku-5-5` is the first Haiku model with effort levels and supports all
208
+ five of them. It uses adaptive thinking and does not support thinking token
209
+ budgets: the AI SDK converts `thinking: { type: 'enabled', budgetTokens }` to
210
+ `{ type: 'adaptive' }` and emits a warning. Use `effort` to control how much it
211
+ thinks. Unlike `claude-sonnet-5-5`, thinking can still be turned off with
212
+ `thinking: { type: 'disabled' }`, but only at `low`, `medium`, and `high` effort.
213
+ Start at `medium` effort and test other levels rather than carrying over the
214
+ settings you used on `claude-haiku-4-5`.
206
215
 
207
216
  On `claude-opus-5-5`, thinking is always adaptive and cannot be disabled, so
208
217
  `effort` is the main control for latency and cost. The API default effort for
@@ -325,6 +334,8 @@ The `inferenceGeo` option accepts `'us'` (US-only infrastructure) or `'global'`
325
334
 
326
335
  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.
327
336
 
337
+ Claude Haiku 5.5 has the same biology safeguards as Claude Sonnet 5 and 5.5, plus safeguards that prevent cyber misuse.
338
+
328
339
  Claude Sonnet 5.5 also has safety classifiers enabled, including for cybersecurity, biology, and reasoning extraction. Requests that ask the model to reproduce its internal reasoning in the response text can be declined with the `reasoning_extraction` category; use `thinking: { type: 'adaptive', display: 'summarized' }` and read the reasoning parts instead.
329
340
 
330
341
  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`.
@@ -2012,6 +2023,7 @@ and the `mediaType` should be set to `'application/pdf'`.
2012
2023
  | `claude-opus-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
2013
2024
  | `claude-sonnet-5-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
2014
2025
  | `claude-sonnet-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
2026
+ | `claude-haiku-5-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
2015
2027
  | `claude-fable-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
2016
2028
  | `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} /> |
2017
2029
  | `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} /> |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/anthropic",
3
- "version": "3.0.127",
3
+ "version": "3.0.129",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -554,6 +554,7 @@ export type AnthropicSpeed = 'fast' | 'standard';
554
554
 
555
555
  export type AnthropicToolChoice =
556
556
  | { type: 'auto' | 'any'; disable_parallel_tool_use?: boolean }
557
+ | { type: 'none' }
557
558
  | { type: 'tool'; name: string; disable_parallel_tool_use?: boolean };
558
559
 
559
560
  export type AnthropicContainer = {
@@ -340,6 +340,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
340
340
  rejectsSamplingParameters,
341
341
  rejectsThinkingDisabledAboveHighEffort,
342
342
  rejectsThinkingDisabled,
343
+ rejectsBudgetThinking,
343
344
  rejectsForcedToolUse,
344
345
  supportsBetweenToolsThinking,
345
346
  isKnownModel,
@@ -488,9 +489,9 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
488
489
  toolsetNames,
489
490
  });
490
491
 
491
- // Some models always run adaptive thinking and reject `disabled` and
492
- // budget-based `enabled` thinking with a 400. Drop the unsupported
493
- // setting and keep the request adaptive so it still succeeds.
492
+ // Some models always run adaptive thinking and reject `disabled` thinking
493
+ // with a 400. Drop the unsupported setting and keep the request adaptive
494
+ // so it still succeeds.
494
495
  if (rejectsThinkingDisabled && anthropicOptions?.thinking != null) {
495
496
  const requestedThinking = anthropicOptions.thinking;
496
497
  const requestedType =
@@ -514,18 +515,30 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
514
515
  `The thinking setting has been removed. Lower 'effort' to reduce thinking.`,
515
516
  });
516
517
  anthropicOptions.thinking = undefined;
517
- } else if (requestedType === 'enabled') {
518
- warnings.push({
519
- type: 'unsupported',
520
- feature: 'providerOptions.anthropic.thinking',
521
- details:
522
- `budget-based thinking is not supported by ${this.modelId}; it always uses adaptive thinking. ` +
523
- `Using adaptive thinking instead. Use 'effort' to control how much the model thinks.`,
524
- });
525
- anthropicOptions.thinking = { type: 'adaptive' };
526
518
  }
527
519
  }
528
520
 
521
+ // Models that only support adaptive thinking reject budget-based thinking
522
+ // with a 400. Use adaptive thinking instead and let `effort` control how
523
+ // much the model thinks.
524
+ if (
525
+ rejectsBudgetThinking &&
526
+ anthropicOptions?.thinking != null &&
527
+ 'type' in anthropicOptions.thinking &&
528
+ anthropicOptions.thinking.type === 'enabled'
529
+ ) {
530
+ warnings.push({
531
+ type: 'unsupported',
532
+ feature: 'providerOptions.anthropic.thinking',
533
+ details: rejectsThinkingDisabled
534
+ ? `budget-based thinking is not supported by ${this.modelId}; it always uses adaptive thinking. ` +
535
+ `Using adaptive thinking instead. Use 'effort' to control how much the model thinks.`
536
+ : `budget-based thinking is not supported by ${this.modelId}. ` +
537
+ `Using adaptive thinking instead. Use 'effort' to control how much the model thinks.`,
538
+ });
539
+ anthropicOptions.thinking = { type: 'adaptive' };
540
+ }
541
+
529
542
  const thinking = anthropicOptions?.thinking;
530
543
  const thinkingType =
531
544
  thinking != null && 'type' in thinking ? thinking.type : undefined;
@@ -2970,6 +2983,11 @@ export function getModelCapabilities(modelId: string): {
2970
2983
  * are rejected with a 400.
2971
2984
  */
2972
2985
  rejectsThinkingDisabled: boolean;
2986
+ /**
2987
+ * Budget-based thinking (`thinking.type` `enabled` with `budget_tokens`) is
2988
+ * rejected with a 400. Only adaptive thinking is supported.
2989
+ */
2990
+ rejectsBudgetThinking: boolean;
2973
2991
  /**
2974
2992
  * Forced tool use (`tool_choice` `any` or a named tool) is rejected with a 400.
2975
2993
  */
@@ -2988,6 +3006,7 @@ export function getModelCapabilities(modelId: string): {
2988
3006
  rejectsSamplingParameters: true,
2989
3007
  rejectsThinkingDisabledAboveHighEffort: true,
2990
3008
  rejectsThinkingDisabled: true,
3009
+ rejectsBudgetThinking: true,
2991
3010
  rejectsForcedToolUse: true,
2992
3011
  supportsBetweenToolsThinking: true,
2993
3012
  isKnownModel: true,
@@ -2999,10 +3018,24 @@ export function getModelCapabilities(modelId: string): {
2999
3018
  rejectsSamplingParameters: true,
3000
3019
  rejectsThinkingDisabledAboveHighEffort: true,
3001
3020
  rejectsThinkingDisabled: true,
3021
+ rejectsBudgetThinking: true,
3002
3022
  rejectsForcedToolUse: true,
3003
3023
  supportsBetweenToolsThinking: false,
3004
3024
  isKnownModel: true,
3005
3025
  };
3026
+ } else if (modelId.includes('claude-haiku-5-5')) {
3027
+ // Thinking can be turned off, but only up to `high` effort.
3028
+ return {
3029
+ maxOutputTokens: 128000,
3030
+ supportsStructuredOutput: true,
3031
+ rejectsSamplingParameters: true,
3032
+ rejectsThinkingDisabledAboveHighEffort: true,
3033
+ rejectsThinkingDisabled: false,
3034
+ rejectsBudgetThinking: true,
3035
+ rejectsForcedToolUse: false,
3036
+ supportsBetweenToolsThinking: false,
3037
+ isKnownModel: true,
3038
+ };
3006
3039
  } else if (modelId.includes('claude-opus-5')) {
3007
3040
  return {
3008
3041
  maxOutputTokens: 128000,
@@ -3010,6 +3043,7 @@ export function getModelCapabilities(modelId: string): {
3010
3043
  rejectsSamplingParameters: true,
3011
3044
  rejectsThinkingDisabledAboveHighEffort: true,
3012
3045
  rejectsThinkingDisabled: false,
3046
+ rejectsBudgetThinking: false,
3013
3047
  rejectsForcedToolUse: false,
3014
3048
  supportsBetweenToolsThinking: false,
3015
3049
  isKnownModel: true,
@@ -3021,6 +3055,7 @@ export function getModelCapabilities(modelId: string): {
3021
3055
  rejectsSamplingParameters: true,
3022
3056
  rejectsThinkingDisabledAboveHighEffort: false,
3023
3057
  rejectsThinkingDisabled: true,
3058
+ rejectsBudgetThinking: true,
3024
3059
  rejectsForcedToolUse: true,
3025
3060
  supportsBetweenToolsThinking: false,
3026
3061
  isKnownModel: true,
@@ -3032,6 +3067,7 @@ export function getModelCapabilities(modelId: string): {
3032
3067
  rejectsSamplingParameters: true,
3033
3068
  rejectsThinkingDisabledAboveHighEffort: false,
3034
3069
  rejectsThinkingDisabled: true,
3070
+ rejectsBudgetThinking: true,
3035
3071
  rejectsForcedToolUse: false,
3036
3072
  supportsBetweenToolsThinking: false,
3037
3073
  isKnownModel: true,
@@ -3047,6 +3083,7 @@ export function getModelCapabilities(modelId: string): {
3047
3083
  rejectsSamplingParameters: true,
3048
3084
  rejectsThinkingDisabledAboveHighEffort: false,
3049
3085
  rejectsThinkingDisabled: false,
3086
+ rejectsBudgetThinking: false,
3050
3087
  rejectsForcedToolUse: false,
3051
3088
  supportsBetweenToolsThinking: false,
3052
3089
  isKnownModel: true,
@@ -3061,6 +3098,7 @@ export function getModelCapabilities(modelId: string): {
3061
3098
  rejectsSamplingParameters: false,
3062
3099
  rejectsThinkingDisabledAboveHighEffort: false,
3063
3100
  rejectsThinkingDisabled: false,
3101
+ rejectsBudgetThinking: false,
3064
3102
  rejectsForcedToolUse: false,
3065
3103
  supportsBetweenToolsThinking: false,
3066
3104
  isKnownModel: true,
@@ -3076,6 +3114,7 @@ export function getModelCapabilities(modelId: string): {
3076
3114
  rejectsSamplingParameters: false,
3077
3115
  rejectsThinkingDisabledAboveHighEffort: false,
3078
3116
  rejectsThinkingDisabled: false,
3117
+ rejectsBudgetThinking: false,
3079
3118
  rejectsForcedToolUse: false,
3080
3119
  supportsBetweenToolsThinking: false,
3081
3120
  isKnownModel: true,
@@ -3087,6 +3126,7 @@ export function getModelCapabilities(modelId: string): {
3087
3126
  rejectsSamplingParameters: false,
3088
3127
  rejectsThinkingDisabledAboveHighEffort: false,
3089
3128
  rejectsThinkingDisabled: false,
3129
+ rejectsBudgetThinking: false,
3090
3130
  rejectsForcedToolUse: false,
3091
3131
  supportsBetweenToolsThinking: false,
3092
3132
  isKnownModel: true,
@@ -3098,6 +3138,7 @@ export function getModelCapabilities(modelId: string): {
3098
3138
  rejectsSamplingParameters: false,
3099
3139
  rejectsThinkingDisabledAboveHighEffort: false,
3100
3140
  rejectsThinkingDisabled: false,
3141
+ rejectsBudgetThinking: false,
3101
3142
  rejectsForcedToolUse: false,
3102
3143
  supportsBetweenToolsThinking: false,
3103
3144
  isKnownModel: true,
@@ -3109,6 +3150,7 @@ export function getModelCapabilities(modelId: string): {
3109
3150
  rejectsSamplingParameters: false,
3110
3151
  rejectsThinkingDisabledAboveHighEffort: false,
3111
3152
  rejectsThinkingDisabled: false,
3153
+ rejectsBudgetThinking: false,
3112
3154
  rejectsForcedToolUse: false,
3113
3155
  supportsBetweenToolsThinking: false,
3114
3156
  isKnownModel: true,
@@ -3120,6 +3162,7 @@ export function getModelCapabilities(modelId: string): {
3120
3162
  rejectsSamplingParameters: false,
3121
3163
  rejectsThinkingDisabledAboveHighEffort: false,
3122
3164
  rejectsThinkingDisabled: false,
3165
+ rejectsBudgetThinking: false,
3123
3166
  rejectsForcedToolUse: false,
3124
3167
  supportsBetweenToolsThinking: false,
3125
3168
  isKnownModel: true,
@@ -3133,6 +3176,7 @@ export function getModelCapabilities(modelId: string): {
3133
3176
  rejectsSamplingParameters: false,
3134
3177
  rejectsThinkingDisabledAboveHighEffort: false,
3135
3178
  rejectsThinkingDisabled: false,
3179
+ rejectsBudgetThinking: false,
3136
3180
  rejectsForcedToolUse: false,
3137
3181
  supportsBetweenToolsThinking: false,
3138
3182
  isKnownModel: false,
@@ -3147,6 +3191,7 @@ export function getModelCapabilities(modelId: string): {
3147
3191
  rejectsSamplingParameters: true,
3148
3192
  rejectsThinkingDisabledAboveHighEffort: true,
3149
3193
  rejectsThinkingDisabled: false,
3194
+ rejectsBudgetThinking: false,
3150
3195
  rejectsForcedToolUse: false,
3151
3196
  supportsBetweenToolsThinking: false,
3152
3197
  isKnownModel: false,
@@ -3160,6 +3205,7 @@ export function getModelCapabilities(modelId: string): {
3160
3205
  rejectsSamplingParameters: false,
3161
3206
  rejectsThinkingDisabledAboveHighEffort: false,
3162
3207
  rejectsThinkingDisabled: false,
3208
+ rejectsBudgetThinking: false,
3163
3209
  rejectsForcedToolUse: false,
3164
3210
  supportsBetweenToolsThinking: false,
3165
3211
  isKnownModel: false,
@@ -5,6 +5,7 @@ export type AnthropicMessagesModelId =
5
5
  | 'claude-3-haiku-20240307'
6
6
  | 'claude-haiku-4-5-20251001'
7
7
  | 'claude-haiku-4-5'
8
+ | 'claude-haiku-5-5'
8
9
  | 'claude-opus-4-0'
9
10
  | 'claude-opus-4-20250514'
10
11
  | 'claude-opus-4-1-20250805'
@@ -477,8 +477,12 @@ export async function prepareTools({
477
477
  betas,
478
478
  };
479
479
  case 'none':
480
- // Anthropic does not support 'none' tool choice, so we remove the tools:
481
- return { tools: undefined, toolChoice: undefined, toolWarnings, betas };
480
+ return {
481
+ tools: anthropicTools,
482
+ toolChoice: { type: 'none' },
483
+ toolWarnings,
484
+ betas,
485
+ };
482
486
  case 'tool':
483
487
  if (rejectsForcedToolUse) {
484
488
  toolWarnings.push({
@@ -1207,6 +1207,30 @@ export async function convertToAnthropicMessagesPrompt({
1207
1207
  ) {
1208
1208
  const output = part.output;
1209
1209
 
1210
+ if (
1211
+ output.type === 'error-json' ||
1212
+ (output.type === 'json' &&
1213
+ output.value != null &&
1214
+ typeof output.value === 'object' &&
1215
+ !Array.isArray(output.value) &&
1216
+ 'type' in output.value &&
1217
+ output.value.type === 'tool_search_tool_result_error')
1218
+ ) {
1219
+ anthropicContent.push({
1220
+ type: 'tool_search_tool_result',
1221
+ tool_use_id: part.toolCallId,
1222
+ content: {
1223
+ type: 'tool_search_tool_result_error',
1224
+ error_code:
1225
+ (await extractErrorValue(output.value)).errorCode ??
1226
+ 'unavailable',
1227
+ },
1228
+ cache_control: cacheControl,
1229
+ });
1230
+
1231
+ break;
1232
+ }
1233
+
1210
1234
  if (output.type !== 'json') {
1211
1235
  warnings.push({
1212
1236
  type: 'other',