@ai-sdk/anthropic 4.0.0-beta.2 → 4.0.0-beta.21

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.
@@ -146,6 +146,12 @@ The following optional provider options are available for Anthropic models:
146
146
  - `"jsonTool"`: Use a special `"json"` tool to specify the structured output format.
147
147
  - `"auto"`: Use `"outputFormat"` when supported, otherwise fall back to `"jsonTool"` (default).
148
148
 
149
+ - `metadata` _object_
150
+
151
+ Optional. Metadata to include with the request. See the [Anthropic API documentation](https://platform.claude.com/docs/en/api/messages/create) for details.
152
+
153
+ - `userId` _string_ - An external identifier for the end-user. Should be a UUID, hash, or other opaque identifier. Must not contain PII.
154
+
149
155
  ### Structured Outputs and Tool Input Streaming
150
156
 
151
157
  Tool call streaming is enabled by default. You can opt out by setting the
@@ -220,17 +226,58 @@ The `speed` option accepts `'fast'` or `'standard'` (default behavior).
220
226
 
221
227
  ### Reasoning
222
228
 
223
- Anthropic has reasoning support for `claude-opus-4-20250514`, `claude-sonnet-4-20250514`, and `claude-sonnet-4-5-20250929` models.
229
+ Anthropic models support extended thinking, where Claude shows its reasoning process before providing a final answer.
224
230
 
225
- You can enable it using the `thinking` provider option
226
- and specifying a thinking budget in tokens.
231
+ #### Adaptive Thinking
232
+
233
+ For newer models (`claude-sonnet-4-6`, `claude-opus-4-6`, and later), use adaptive thinking.
234
+ Claude automatically determines how much reasoning to use based on the complexity of the prompt.
227
235
 
228
236
  ```ts highlight="4,8-10"
229
237
  import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
230
238
  import { generateText } from 'ai';
231
239
 
232
240
  const { text, reasoningText, reasoning } = await generateText({
233
- model: anthropic('claude-opus-4-20250514'),
241
+ model: anthropic('claude-opus-4-6'),
242
+ prompt: 'How many people will live in the world in 2040?',
243
+ providerOptions: {
244
+ anthropic: {
245
+ thinking: { type: 'adaptive' },
246
+ } satisfies AnthropicLanguageModelOptions,
247
+ },
248
+ });
249
+
250
+ console.log(reasoningText); // reasoning text
251
+ console.log(reasoning); // reasoning details including redacted reasoning
252
+ console.log(text); // text response
253
+ ```
254
+
255
+ You can combine adaptive thinking with the `effort` option to control how much reasoning Claude uses:
256
+
257
+ ```ts highlight="6-8"
258
+ const { text } = await generateText({
259
+ model: anthropic('claude-opus-4-6'),
260
+ prompt: 'Invent a new holiday and describe its traditions.',
261
+ providerOptions: {
262
+ anthropic: {
263
+ thinking: { type: 'adaptive' },
264
+ effort: 'max', // 'low' | 'medium' | 'high' | 'max'
265
+ } satisfies AnthropicLanguageModelOptions,
266
+ },
267
+ });
268
+ ```
269
+
270
+ #### Budget-Based Thinking
271
+
272
+ For earlier models (`claude-opus-4-20250514`, `claude-sonnet-4-20250514`, `claude-sonnet-4-5-20250929`),
273
+ use `type: 'enabled'` with an explicit token budget:
274
+
275
+ ```ts highlight="4,8-10"
276
+ import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
277
+ import { generateText } from 'ai';
278
+
279
+ const { text, reasoningText, reasoning } = await generateText({
280
+ model: anthropic('claude-sonnet-4-5-20250929'),
234
281
  prompt: 'How many people will live in the world in 2040?',
235
282
  providerOptions: {
236
283
  anthropic: {
@@ -1114,12 +1161,12 @@ import {
1114
1161
  anthropic,
1115
1162
  forwardAnthropicContainerIdFromLastStep,
1116
1163
  } from '@ai-sdk/anthropic';
1117
- import { generateText, tool, stepCountIs } from 'ai';
1164
+ import { generateText, tool, isStepCount } from 'ai';
1118
1165
  import { z } from 'zod';
1119
1166
 
1120
1167
  const result = await generateText({
1121
1168
  model: anthropic('claude-sonnet-4-5'),
1122
- stopWhen: stepCountIs(10),
1169
+ stopWhen: isStepCount(10),
1123
1170
  prompt:
1124
1171
  'Get the weather for Tokyo, Sydney, and London, then calculate the average temperature.',
1125
1172
  tools: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/anthropic",
3
- "version": "4.0.0-beta.2",
3
+ "version": "4.0.0-beta.21",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -36,8 +36,8 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@ai-sdk/provider": "4.0.0-beta.0",
40
- "@ai-sdk/provider-utils": "5.0.0-beta.1"
39
+ "@ai-sdk/provider": "4.0.0-beta.8",
40
+ "@ai-sdk/provider-utils": "5.0.0-beta.14"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "20.17.24",
@@ -71,9 +71,7 @@
71
71
  "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
72
72
  "build:watch": "pnpm clean && tsup --watch --tsconfig tsconfig.build.json",
73
73
  "clean": "del-cli dist docs *.tsbuildinfo",
74
- "lint": "eslint \"./**/*.ts*\"",
75
74
  "type-check": "tsc --build",
76
- "prettier-check": "prettier --check \"./**/*.ts*\"",
77
75
  "test": "pnpm test:node && pnpm test:edge",
78
76
  "test:update": "pnpm test:node -u",
79
77
  "test:watch": "vitest --config vitest.node.config.js",
@@ -0,0 +1,106 @@
1
+ import {
2
+ FilesV4,
3
+ FilesV4UploadFileCallOptions,
4
+ FilesV4UploadFileResult,
5
+ } from '@ai-sdk/provider';
6
+ import {
7
+ combineHeaders,
8
+ convertBase64ToUint8Array,
9
+ createJsonResponseHandler,
10
+ FetchFunction,
11
+ lazySchema,
12
+ parseProviderOptions,
13
+ postFormDataToApi,
14
+ zodSchema,
15
+ } from '@ai-sdk/provider-utils';
16
+ import { z } from 'zod/v4';
17
+ import { anthropicFailedResponseHandler } from './anthropic-error';
18
+
19
+ const anthropicUploadFileProviderOptions = z.object({});
20
+
21
+ const anthropicUploadFileResponseSchema = lazySchema(() =>
22
+ zodSchema(
23
+ z.object({
24
+ id: z.string(),
25
+ type: z.literal('file'),
26
+ filename: z.string(),
27
+ mime_type: z.string(),
28
+ size_bytes: z.number(),
29
+ created_at: z.string(),
30
+ downloadable: z.boolean().nullish(),
31
+ }),
32
+ ),
33
+ );
34
+
35
+ interface AnthropicFilesConfig {
36
+ provider: string;
37
+ baseURL: string;
38
+ headers: () => Record<string, string | undefined>;
39
+ fetch?: FetchFunction;
40
+ }
41
+
42
+ export class AnthropicFiles implements FilesV4 {
43
+ readonly specificationVersion = 'v4';
44
+
45
+ get provider(): string {
46
+ return this.config.provider;
47
+ }
48
+
49
+ constructor(private readonly config: AnthropicFilesConfig) {}
50
+
51
+ async uploadFile({
52
+ data,
53
+ mediaType,
54
+ filename,
55
+ providerOptions,
56
+ }: FilesV4UploadFileCallOptions): Promise<FilesV4UploadFileResult> {
57
+ const anthropicOptions = await parseProviderOptions({
58
+ provider: 'anthropic',
59
+ providerOptions,
60
+ schema: zodSchema(anthropicUploadFileProviderOptions),
61
+ });
62
+
63
+ const fileBytes =
64
+ data instanceof Uint8Array ? data : convertBase64ToUint8Array(data);
65
+
66
+ const blob = new Blob([fileBytes], { type: mediaType });
67
+
68
+ const formData = new FormData();
69
+ if (filename != null) {
70
+ formData.append('file', blob, filename);
71
+ } else {
72
+ formData.append('file', blob);
73
+ }
74
+
75
+ const { value: response } = await postFormDataToApi({
76
+ url: `${this.config.baseURL}/files`,
77
+ headers: combineHeaders(this.config.headers(), {
78
+ 'anthropic-beta': 'files-api-2025-04-14',
79
+ }),
80
+ formData,
81
+ failedResponseHandler: anthropicFailedResponseHandler,
82
+ successfulResponseHandler: createJsonResponseHandler(
83
+ anthropicUploadFileResponseSchema,
84
+ ),
85
+ fetch: this.config.fetch,
86
+ });
87
+
88
+ return {
89
+ warnings: [],
90
+ providerReference: { anthropic: response.id },
91
+ mediaType: response.mime_type ?? mediaType,
92
+ filename: response.filename ?? filename,
93
+ providerMetadata: {
94
+ anthropic: {
95
+ filename: response.filename,
96
+ mimeType: response.mime_type,
97
+ sizeBytes: response.size_bytes,
98
+ createdAt: response.created_at,
99
+ ...(response.downloadable != null
100
+ ? { downloadable: response.downloadable }
101
+ : {}),
102
+ },
103
+ },
104
+ };
105
+ }
106
+ }
@@ -87,6 +87,10 @@ type AnthropicContentSource =
87
87
  type: 'text';
88
88
  media_type: 'text/plain';
89
89
  data: string;
90
+ }
91
+ | {
92
+ type: 'file';
93
+ file_id: string;
90
94
  };
91
95
 
92
96
  export interface AnthropicImageContent {
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  APICallError,
3
3
  JSONObject,
4
- LanguageModelV3,
5
- LanguageModelV3CallOptions,
6
- LanguageModelV3Content,
7
- LanguageModelV3FinishReason,
8
- LanguageModelV3FunctionTool,
9
- LanguageModelV3GenerateResult,
10
- LanguageModelV3Prompt,
11
- LanguageModelV3Source,
12
- LanguageModelV3StreamPart,
13
- LanguageModelV3StreamResult,
14
- LanguageModelV3ToolCall,
15
- SharedV3ProviderMetadata,
16
- SharedV3Warning,
4
+ LanguageModelV4,
5
+ LanguageModelV4CallOptions,
6
+ LanguageModelV4Content,
7
+ LanguageModelV4FinishReason,
8
+ LanguageModelV4FunctionTool,
9
+ LanguageModelV4GenerateResult,
10
+ LanguageModelV4Prompt,
11
+ LanguageModelV4Source,
12
+ LanguageModelV4StreamPart,
13
+ LanguageModelV4StreamResult,
14
+ LanguageModelV4ToolCall,
15
+ SharedV4ProviderMetadata,
16
+ SharedV4Warning,
17
17
  } from '@ai-sdk/provider';
18
18
  import {
19
19
  combineHeaders,
@@ -23,11 +23,15 @@ import {
23
23
  FetchFunction,
24
24
  generateId,
25
25
  InferSchema,
26
+ isCustomReasoning,
27
+ mapReasoningToProviderBudget,
28
+ mapReasoningToProviderEffort,
26
29
  parseProviderOptions,
27
30
  ParseResult,
28
31
  postJsonToApi,
29
32
  Resolvable,
30
33
  resolve,
34
+ resolveProviderReference,
31
35
  } from '@ai-sdk/provider-utils';
32
36
  import { anthropicFailedResponseHandler } from './anthropic-error';
33
37
  import { AnthropicMessageMetadata } from './anthropic-message-metadata';
@@ -42,6 +46,7 @@ import {
42
46
  } from './anthropic-messages-api';
43
47
  import {
44
48
  AnthropicMessagesModelId,
49
+ AnthropicLanguageModelOptions,
45
50
  anthropicLanguageModelOptions,
46
51
  } from './anthropic-messages-options';
47
52
  import { prepareTools } from './anthropic-prepare-tools';
@@ -61,7 +66,7 @@ function createCitationSource(
61
66
  mediaType: string;
62
67
  }>,
63
68
  generateId: () => string,
64
- ): LanguageModelV3Source | undefined {
69
+ ): LanguageModelV4Source | undefined {
65
70
  if (citation.type === 'web_search_result_location') {
66
71
  return {
67
72
  type: 'source' as const,
@@ -74,7 +79,7 @@ function createCitationSource(
74
79
  citedText: citation.cited_text,
75
80
  encryptedIndex: citation.encrypted_index,
76
81
  },
77
- } satisfies SharedV3ProviderMetadata,
82
+ } satisfies SharedV4ProviderMetadata,
78
83
  };
79
84
  }
80
85
 
@@ -108,7 +113,7 @@ function createCitationSource(
108
113
  startCharIndex: citation.start_char_index,
109
114
  endCharIndex: citation.end_char_index,
110
115
  },
111
- } satisfies SharedV3ProviderMetadata,
116
+ } satisfies SharedV4ProviderMetadata,
112
117
  };
113
118
  }
114
119
 
@@ -122,17 +127,23 @@ type AnthropicMessagesConfig = {
122
127
  args: Record<string, any>,
123
128
  betas: Set<string>,
124
129
  ) => Record<string, any>;
125
- supportedUrls?: () => LanguageModelV3['supportedUrls'];
130
+ supportedUrls?: () => LanguageModelV4['supportedUrls'];
126
131
  generateId?: () => string;
127
132
 
128
133
  /**
129
134
  * When false, the model will use JSON tool fallback for structured outputs.
130
135
  */
131
136
  supportsNativeStructuredOutput?: boolean;
137
+
138
+ /**
139
+ * When false, `strict` on tool definitions will be ignored and a warning emitted.
140
+ * Defaults to true.
141
+ */
142
+ supportsStrictTools?: boolean;
132
143
  };
133
144
 
134
- export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
135
- readonly specificationVersion = 'v3';
145
+ export class AnthropicMessagesLanguageModel implements LanguageModelV4 {
146
+ readonly specificationVersion = 'v4';
136
147
 
137
148
  readonly modelId: AnthropicMessagesModelId;
138
149
 
@@ -184,13 +195,14 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
184
195
  seed,
185
196
  tools,
186
197
  toolChoice,
198
+ reasoning,
187
199
  providerOptions,
188
200
  stream,
189
- }: LanguageModelV3CallOptions & {
201
+ }: LanguageModelV4CallOptions & {
190
202
  stream: boolean;
191
203
  userSuppliedBetas: Set<string>;
192
204
  }) {
193
- const warnings: SharedV3Warning[] = [];
205
+ const warnings: SharedV4Warning[] = [];
194
206
 
195
207
  if (frequencyPenalty != null) {
196
208
  warnings.push({ type: 'unsupported', feature: 'frequencyPenalty' });
@@ -263,20 +275,27 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
263
275
  const {
264
276
  maxOutputTokens: maxOutputTokensForModel,
265
277
  supportsStructuredOutput: modelSupportsStructuredOutput,
278
+ supportsAdaptiveThinking,
266
279
  isKnownModel,
267
280
  } = getModelCapabilities(this.modelId);
268
281
 
282
+ const isAnthropicModel = isKnownModel || this.modelId.startsWith('claude-');
283
+
269
284
  const supportsStructuredOutput =
270
285
  (this.config.supportsNativeStructuredOutput ?? true) &&
271
286
  modelSupportsStructuredOutput;
272
287
 
288
+ const supportsStrictTools =
289
+ (this.config.supportsStrictTools ?? true) &&
290
+ modelSupportsStructuredOutput;
291
+
273
292
  const structureOutputMode =
274
293
  anthropicOptions?.structuredOutputMode ?? 'auto';
275
294
  const useStructuredOutput =
276
295
  structureOutputMode === 'outputFormat' ||
277
296
  (structureOutputMode === 'auto' && supportsStructuredOutput);
278
297
 
279
- const jsonResponseTool: LanguageModelV3FunctionTool | undefined =
298
+ const jsonResponseTool: LanguageModelV4FunctionTool | undefined =
280
299
  responseFormat?.type === 'json' &&
281
300
  responseFormat.schema != null &&
282
301
  !useStructuredOutput
@@ -326,6 +345,29 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
326
345
  toolNameMapping,
327
346
  });
328
347
 
348
+ /*
349
+ * Map top-level `reasoning` to Anthropic thinking/effort when provider
350
+ * options don't already specify them. Provider options always take precedence.
351
+ */
352
+ if (
353
+ isCustomReasoning(reasoning) &&
354
+ anthropicOptions?.thinking == null &&
355
+ anthropicOptions?.effort == null
356
+ ) {
357
+ const reasoningConfig = resolveAnthropicReasoningConfig({
358
+ reasoning,
359
+ supportsAdaptiveThinking,
360
+ maxOutputTokensForModel,
361
+ warnings,
362
+ });
363
+ if (reasoningConfig != null) {
364
+ anthropicOptions.thinking = reasoningConfig.thinking;
365
+ if (reasoningConfig.effort != null) {
366
+ anthropicOptions.effort = reasoningConfig.effort;
367
+ }
368
+ }
369
+ }
370
+
329
371
  const thinkingType = anthropicOptions?.thinking?.type;
330
372
  const isThinking =
331
373
  thinkingType === 'enabled' || thinkingType === 'adaptive';
@@ -378,6 +420,9 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
378
420
  ...(anthropicOptions?.cacheControl && {
379
421
  cache_control: anthropicOptions.cacheControl,
380
422
  }),
423
+ ...(anthropicOptions?.metadata?.userId != null && {
424
+ metadata: { user_id: anthropicOptions.metadata.userId },
425
+ }),
381
426
 
382
427
  // mcp servers:
383
428
  ...(anthropicOptions?.mcpServers &&
@@ -406,7 +451,13 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
406
451
  id: anthropicOptions.container.id,
407
452
  skills: anthropicOptions.container.skills.map(skill => ({
408
453
  type: skill.type,
409
- skill_id: skill.skillId,
454
+ skill_id:
455
+ skill.type === 'custom'
456
+ ? resolveProviderReference({
457
+ reference: skill.providerReference,
458
+ provider: 'anthropic',
459
+ })
460
+ : skill.skillId,
410
461
  version: skill.version,
411
462
  })),
412
463
  } satisfies AnthropicContainer)
@@ -522,8 +573,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
522
573
  // adjust max tokens to account for thinking:
523
574
  baseArgs.max_tokens = maxTokens + (thinkingBudget ?? 0);
524
575
  } else {
525
- // Only check temperature/topP mutual exclusivity when thinking is not enabled
526
- if (topP != null && temperature != null) {
576
+ // Only check temperature/topP mutual exclusivity for known Anthropic models
577
+ // when thinking is not enabled. Non-Anthropic models using the Anthropic-compatible
578
+ // API (e.g. Minimax) may require both parameters to be set.
579
+ if (isAnthropicModel && topP != null && temperature != null) {
527
580
  warnings.push({
528
581
  type: 'unsupported',
529
582
  feature: 'topP',
@@ -614,6 +667,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
614
667
  disableParallelToolUse: true,
615
668
  cacheControlValidator,
616
669
  supportsStructuredOutput: false,
670
+ supportsStrictTools,
617
671
  }
618
672
  : {
619
673
  tools: tools ?? [],
@@ -621,6 +675,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
621
675
  disableParallelToolUse: anthropicOptions?.disableParallelToolUse,
622
676
  cacheControlValidator,
623
677
  supportsStructuredOutput,
678
+ supportsStrictTools,
624
679
  },
625
680
  );
626
681
 
@@ -694,7 +749,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
694
749
  return this.config.transformRequestBody?.(args, betas) ?? args;
695
750
  }
696
751
 
697
- private extractCitationDocuments(prompt: LanguageModelV3Prompt): Array<{
752
+ private extractCitationDocuments(prompt: LanguageModelV4Prompt): Array<{
698
753
  title: string;
699
754
  filename?: string;
700
755
  mediaType: string;
@@ -738,8 +793,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
738
793
  }
739
794
 
740
795
  async doGenerate(
741
- options: LanguageModelV3CallOptions,
742
- ): Promise<LanguageModelV3GenerateResult> {
796
+ options: LanguageModelV4CallOptions,
797
+ ): Promise<LanguageModelV4GenerateResult> {
743
798
  const {
744
799
  args,
745
800
  warnings,
@@ -779,8 +834,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
779
834
  fetch: this.config.fetch,
780
835
  });
781
836
 
782
- const content: Array<LanguageModelV3Content> = [];
783
- const mcpToolCalls: Record<string, LanguageModelV3ToolCall> = {};
837
+ const content: Array<LanguageModelV4Content> = [];
838
+ const mcpToolCalls: Record<string, LanguageModelV4ToolCall> = {};
784
839
  const serverToolCalls: Record<string, string> = {}; // tool_use_id -> provider tool name
785
840
  let isJsonResponseFromTool = false;
786
841
 
@@ -1205,7 +1260,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1205
1260
  ) ?? null,
1206
1261
  } satisfies AnthropicMessageMetadata;
1207
1262
 
1208
- const providerMetadata: SharedV3ProviderMetadata = {
1263
+ const providerMetadata: SharedV4ProviderMetadata = {
1209
1264
  anthropic: anthropicMetadata,
1210
1265
  };
1211
1266
 
@@ -1219,8 +1274,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1219
1274
  }
1220
1275
 
1221
1276
  async doStream(
1222
- options: LanguageModelV3CallOptions,
1223
- ): Promise<LanguageModelV3StreamResult> {
1277
+ options: LanguageModelV4CallOptions,
1278
+ ): Promise<LanguageModelV4StreamResult> {
1224
1279
  const {
1225
1280
  args: body,
1226
1281
  warnings,
@@ -1257,7 +1312,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1257
1312
  fetch: this.config.fetch,
1258
1313
  });
1259
1314
 
1260
- let finishReason: LanguageModelV3FinishReason = {
1315
+ let finishReason: LanguageModelV4FinishReason = {
1261
1316
  unified: 'other',
1262
1317
  raw: undefined,
1263
1318
  };
@@ -1289,7 +1344,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1289
1344
  }
1290
1345
  | { type: 'text' | 'reasoning' }
1291
1346
  > = {};
1292
- const mcpToolCalls: Record<string, LanguageModelV3ToolCall> = {};
1347
+ const mcpToolCalls: Record<string, LanguageModelV4ToolCall> = {};
1293
1348
  const serverToolCalls: Record<string, string> = {}; // tool_use_id -> provider tool name
1294
1349
 
1295
1350
  let contextManagement:
@@ -1323,7 +1378,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1323
1378
  const transformedStream = response.pipeThrough(
1324
1379
  new TransformStream<
1325
1380
  ParseResult<InferSchema<typeof anthropicMessagesChunkSchema>>,
1326
- LanguageModelV3StreamPart
1381
+ LanguageModelV4StreamPart
1327
1382
  >({
1328
1383
  start(controller) {
1329
1384
  controller.enqueue({ type: 'stream-start', warnings });
@@ -2176,7 +2231,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
2176
2231
  contextManagement,
2177
2232
  } satisfies AnthropicMessageMetadata;
2178
2233
 
2179
- const providerMetadata: SharedV3ProviderMetadata = {
2234
+ const providerMetadata: SharedV4ProviderMetadata = {
2180
2235
  anthropic: anthropicMetadata,
2181
2236
  };
2182
2237
 
@@ -2259,9 +2314,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
2259
2314
  * @see https://docs.claude.com/en/docs/about-claude/models/overview#model-comparison-table
2260
2315
  * @see https://platform.claude.com/docs/en/build-with-claude/structured-outputs
2261
2316
  */
2262
- function getModelCapabilities(modelId: string): {
2317
+ export function getModelCapabilities(modelId: string): {
2263
2318
  maxOutputTokens: number;
2264
2319
  supportsStructuredOutput: boolean;
2320
+ supportsAdaptiveThinking: boolean;
2265
2321
  isKnownModel: boolean;
2266
2322
  } {
2267
2323
  if (
@@ -2271,6 +2327,7 @@ function getModelCapabilities(modelId: string): {
2271
2327
  return {
2272
2328
  maxOutputTokens: 128000,
2273
2329
  supportsStructuredOutput: true,
2330
+ supportsAdaptiveThinking: true,
2274
2331
  isKnownModel: true,
2275
2332
  };
2276
2333
  } else if (
@@ -2281,36 +2338,42 @@ function getModelCapabilities(modelId: string): {
2281
2338
  return {
2282
2339
  maxOutputTokens: 64000,
2283
2340
  supportsStructuredOutput: true,
2341
+ supportsAdaptiveThinking: false,
2284
2342
  isKnownModel: true,
2285
2343
  };
2286
2344
  } else if (modelId.includes('claude-opus-4-1')) {
2287
2345
  return {
2288
2346
  maxOutputTokens: 32000,
2289
2347
  supportsStructuredOutput: true,
2348
+ supportsAdaptiveThinking: false,
2290
2349
  isKnownModel: true,
2291
2350
  };
2292
2351
  } else if (modelId.includes('claude-sonnet-4-')) {
2293
2352
  return {
2294
2353
  maxOutputTokens: 64000,
2295
2354
  supportsStructuredOutput: false,
2355
+ supportsAdaptiveThinking: false,
2296
2356
  isKnownModel: true,
2297
2357
  };
2298
2358
  } else if (modelId.includes('claude-opus-4-')) {
2299
2359
  return {
2300
2360
  maxOutputTokens: 32000,
2301
2361
  supportsStructuredOutput: false,
2362
+ supportsAdaptiveThinking: false,
2302
2363
  isKnownModel: true,
2303
2364
  };
2304
2365
  } else if (modelId.includes('claude-3-haiku')) {
2305
2366
  return {
2306
2367
  maxOutputTokens: 4096,
2307
2368
  supportsStructuredOutput: false,
2369
+ supportsAdaptiveThinking: false,
2308
2370
  isKnownModel: true,
2309
2371
  };
2310
2372
  } else {
2311
2373
  return {
2312
2374
  maxOutputTokens: 4096,
2313
2375
  supportsStructuredOutput: false,
2376
+ supportsAdaptiveThinking: false,
2314
2377
  isKnownModel: false,
2315
2378
  };
2316
2379
  }
@@ -2341,6 +2404,52 @@ function hasWebTool20260209WithoutCodeExecution(
2341
2404
  return hasWebTool20260209 && !hasCodeExecutionTool;
2342
2405
  }
2343
2406
 
2407
+ function resolveAnthropicReasoningConfig({
2408
+ reasoning,
2409
+ supportsAdaptiveThinking,
2410
+ maxOutputTokensForModel,
2411
+ warnings,
2412
+ }: {
2413
+ reasoning: LanguageModelV4CallOptions['reasoning'];
2414
+ supportsAdaptiveThinking: boolean;
2415
+ maxOutputTokensForModel: number;
2416
+ warnings: SharedV4Warning[];
2417
+ }): Pick<AnthropicLanguageModelOptions, 'thinking' | 'effort'> | undefined {
2418
+ if (!isCustomReasoning(reasoning)) {
2419
+ return undefined;
2420
+ }
2421
+
2422
+ if (reasoning === 'none') {
2423
+ return { thinking: { type: 'disabled' } };
2424
+ }
2425
+
2426
+ if (supportsAdaptiveThinking) {
2427
+ const effort = mapReasoningToProviderEffort({
2428
+ reasoning,
2429
+ effortMap: {
2430
+ minimal: 'low' as const,
2431
+ low: 'low' as const,
2432
+ medium: 'medium' as const,
2433
+ high: 'high' as const,
2434
+ xhigh: 'max' as const,
2435
+ },
2436
+ warnings,
2437
+ });
2438
+ return { thinking: { type: 'adaptive' }, effort };
2439
+ }
2440
+
2441
+ const budgetTokens = mapReasoningToProviderBudget({
2442
+ reasoning,
2443
+ maxOutputTokens: maxOutputTokensForModel,
2444
+ maxReasoningBudget: maxOutputTokensForModel,
2445
+ warnings,
2446
+ });
2447
+ if (budgetTokens == null) {
2448
+ return undefined;
2449
+ }
2450
+ return { thinking: { type: 'enabled', budgetTokens } };
2451
+ }
2452
+
2344
2453
  function mapAnthropicResponseContextManagement(
2345
2454
  contextManagement: AnthropicResponseContextManagement | null | undefined,
2346
2455
  ): AnthropicMessageMetadata['contextManagement'] | null {