@fairyhunter13/ai-anthropic 3.0.58-fork.2 → 3.0.58-fork.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.
@@ -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,
@@ -29,6 +29,87 @@ import {
29
29
  Resolvable,
30
30
  resolve,
31
31
  } from '@ai-sdk/provider-utils';
32
+
33
+ // Inlined from @ai-sdk/provider-utils (4.x) — not available in 3.x provider-utils
34
+ type ReasoningLevel = Exclude<
35
+ LanguageModelV4CallOptions['reasoning'],
36
+ 'none' | 'provider-default' | undefined
37
+ >;
38
+
39
+ function isCustomReasoning(
40
+ reasoning: LanguageModelV4CallOptions['reasoning'],
41
+ ): reasoning is Exclude<
42
+ LanguageModelV4CallOptions['reasoning'],
43
+ 'provider-default' | undefined
44
+ > {
45
+ return reasoning !== undefined && reasoning !== 'provider-default';
46
+ }
47
+
48
+ function mapReasoningToProviderEffort<T extends string>({
49
+ reasoning,
50
+ effortMap,
51
+ warnings,
52
+ }: {
53
+ reasoning: ReasoningLevel;
54
+ effortMap: Partial<Record<ReasoningLevel, T>>;
55
+ warnings: SharedV4Warning[];
56
+ }): T | undefined {
57
+ const mapped = effortMap[reasoning];
58
+ if (mapped == null) {
59
+ warnings.push({
60
+ type: 'unsupported',
61
+ feature: 'reasoning',
62
+ details: `reasoning "${reasoning}" is not supported by this model.`,
63
+ });
64
+ return undefined;
65
+ }
66
+ if (mapped !== reasoning) {
67
+ warnings.push({
68
+ type: 'compatibility',
69
+ feature: 'reasoning',
70
+ details: `reasoning "${reasoning}" is not directly supported by this model. mapped to effort "${mapped}".`,
71
+ });
72
+ }
73
+ return mapped;
74
+ }
75
+
76
+ const DEFAULT_REASONING_BUDGET_PERCENTAGES: Record<ReasoningLevel, number> = {
77
+ minimal: 0.02,
78
+ low: 0.1,
79
+ medium: 0.3,
80
+ high: 0.6,
81
+ xhigh: 0.9,
82
+ };
83
+
84
+ function mapReasoningToProviderBudget({
85
+ reasoning,
86
+ maxOutputTokens,
87
+ maxReasoningBudget,
88
+ minReasoningBudget = 1024,
89
+ budgetPercentages = DEFAULT_REASONING_BUDGET_PERCENTAGES,
90
+ warnings,
91
+ }: {
92
+ reasoning: ReasoningLevel;
93
+ maxOutputTokens: number;
94
+ maxReasoningBudget: number;
95
+ minReasoningBudget?: number;
96
+ budgetPercentages?: Partial<Record<ReasoningLevel, number>>;
97
+ warnings: SharedV4Warning[];
98
+ }): number | undefined {
99
+ const pct = budgetPercentages[reasoning];
100
+ if (pct == null) {
101
+ warnings.push({
102
+ type: 'unsupported',
103
+ feature: 'reasoning',
104
+ details: `reasoning "${reasoning}" is not supported by this model.`,
105
+ });
106
+ return undefined;
107
+ }
108
+ return Math.min(
109
+ maxReasoningBudget,
110
+ Math.max(minReasoningBudget, Math.round(maxOutputTokens * pct)),
111
+ );
112
+ }
32
113
  import { anthropicFailedResponseHandler } from './anthropic-error';
33
114
  import { AnthropicMessageMetadata } from './anthropic-message-metadata';
34
115
  import {
@@ -42,6 +123,7 @@ import {
42
123
  } from './anthropic-messages-api';
43
124
  import {
44
125
  AnthropicMessagesModelId,
126
+ AnthropicLanguageModelOptions,
45
127
  anthropicLanguageModelOptions,
46
128
  } from './anthropic-messages-options';
47
129
  import { prepareTools } from './anthropic-prepare-tools';
@@ -61,7 +143,7 @@ function createCitationSource(
61
143
  mediaType: string;
62
144
  }>,
63
145
  generateId: () => string,
64
- ): LanguageModelV3Source | undefined {
146
+ ): LanguageModelV4Source | undefined {
65
147
  if (citation.type === 'web_search_result_location') {
66
148
  return {
67
149
  type: 'source' as const,
@@ -74,7 +156,7 @@ function createCitationSource(
74
156
  citedText: citation.cited_text,
75
157
  encryptedIndex: citation.encrypted_index,
76
158
  },
77
- } satisfies SharedV3ProviderMetadata,
159
+ } satisfies SharedV4ProviderMetadata,
78
160
  };
79
161
  }
80
162
 
@@ -108,7 +190,7 @@ function createCitationSource(
108
190
  startCharIndex: citation.start_char_index,
109
191
  endCharIndex: citation.end_char_index,
110
192
  },
111
- } satisfies SharedV3ProviderMetadata,
193
+ } satisfies SharedV4ProviderMetadata,
112
194
  };
113
195
  }
114
196
 
@@ -122,17 +204,23 @@ type AnthropicMessagesConfig = {
122
204
  args: Record<string, any>,
123
205
  betas: Set<string>,
124
206
  ) => Record<string, any>;
125
- supportedUrls?: () => LanguageModelV3['supportedUrls'];
207
+ supportedUrls?: () => LanguageModelV4['supportedUrls'];
126
208
  generateId?: () => string;
127
209
 
128
210
  /**
129
211
  * When false, the model will use JSON tool fallback for structured outputs.
130
212
  */
131
213
  supportsNativeStructuredOutput?: boolean;
214
+
215
+ /**
216
+ * When false, `strict` on tool definitions will be ignored and a warning emitted.
217
+ * Defaults to true.
218
+ */
219
+ supportsStrictTools?: boolean;
132
220
  };
133
221
 
134
- export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
135
- readonly specificationVersion = 'v3';
222
+ export class AnthropicMessagesLanguageModel implements LanguageModelV4 {
223
+ readonly specificationVersion = 'v4';
136
224
 
137
225
  readonly modelId: AnthropicMessagesModelId;
138
226
 
@@ -184,13 +272,14 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
184
272
  seed,
185
273
  tools,
186
274
  toolChoice,
275
+ reasoning,
187
276
  providerOptions,
188
277
  stream,
189
- }: LanguageModelV3CallOptions & {
278
+ }: LanguageModelV4CallOptions & {
190
279
  stream: boolean;
191
280
  userSuppliedBetas: Set<string>;
192
281
  }) {
193
- const warnings: SharedV3Warning[] = [];
282
+ const warnings: SharedV4Warning[] = [];
194
283
 
195
284
  if (frequencyPenalty != null) {
196
285
  warnings.push({ type: 'unsupported', feature: 'frequencyPenalty' });
@@ -263,6 +352,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
263
352
  const {
264
353
  maxOutputTokens: maxOutputTokensForModel,
265
354
  supportsStructuredOutput: modelSupportsStructuredOutput,
355
+ supportsAdaptiveThinking,
266
356
  isKnownModel,
267
357
  } = getModelCapabilities(this.modelId);
268
358
 
@@ -270,13 +360,17 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
270
360
  (this.config.supportsNativeStructuredOutput ?? true) &&
271
361
  modelSupportsStructuredOutput;
272
362
 
363
+ const supportsStrictTools =
364
+ (this.config.supportsStrictTools ?? true) &&
365
+ modelSupportsStructuredOutput;
366
+
273
367
  const structureOutputMode =
274
368
  anthropicOptions?.structuredOutputMode ?? 'auto';
275
369
  const useStructuredOutput =
276
370
  structureOutputMode === 'outputFormat' ||
277
371
  (structureOutputMode === 'auto' && supportsStructuredOutput);
278
372
 
279
- const jsonResponseTool: LanguageModelV3FunctionTool | undefined =
373
+ const jsonResponseTool: LanguageModelV4FunctionTool | undefined =
280
374
  responseFormat?.type === 'json' &&
281
375
  responseFormat.schema != null &&
282
376
  !useStructuredOutput
@@ -311,6 +405,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
311
405
  'anthropic.web_search_20250305': 'web_search',
312
406
  'anthropic.web_search_20260209': 'web_search',
313
407
  'anthropic.web_fetch_20250910': 'web_fetch',
408
+ 'anthropic.web_fetch_20260309': 'web_fetch',
314
409
  'anthropic.web_fetch_20260209': 'web_fetch',
315
410
  'anthropic.tool_search_regex_20251119': 'tool_search_tool_regex',
316
411
  'anthropic.tool_search_bm25_20251119': 'tool_search_tool_bm25',
@@ -326,6 +421,29 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
326
421
  toolNameMapping,
327
422
  });
328
423
 
424
+ /*
425
+ * Map top-level `reasoning` to Anthropic thinking/effort when provider
426
+ * options don't already specify them. Provider options always take precedence.
427
+ */
428
+ if (
429
+ isCustomReasoning(reasoning) &&
430
+ anthropicOptions?.thinking == null &&
431
+ anthropicOptions?.effort == null
432
+ ) {
433
+ const reasoningConfig = resolveAnthropicReasoningConfig({
434
+ reasoning,
435
+ supportsAdaptiveThinking,
436
+ maxOutputTokensForModel,
437
+ warnings,
438
+ });
439
+ if (reasoningConfig != null) {
440
+ anthropicOptions.thinking = reasoningConfig.thinking;
441
+ if (reasoningConfig.effort != null) {
442
+ anthropicOptions.effort = reasoningConfig.effort;
443
+ }
444
+ }
445
+ }
446
+
329
447
  // Handle assistant prefill: append a partial assistant message
330
448
  if (anthropicOptions?.prefill) {
331
449
  const lastMessage =
@@ -405,9 +523,22 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
405
523
  ...(anthropicOptions?.speed && {
406
524
  speed: anthropicOptions.speed,
407
525
  }),
526
+ ...(anthropicOptions?.metadata && {
527
+ metadata: {
528
+ ...(anthropicOptions.metadata.userId && {
529
+ user_id: anthropicOptions.metadata.userId,
530
+ }),
531
+ },
532
+ }),
533
+ ...(anthropicOptions?.serviceTier && {
534
+ service_tier: anthropicOptions.serviceTier,
535
+ }),
408
536
  ...(anthropicOptions?.cacheControl && {
409
537
  cache_control: anthropicOptions.cacheControl,
410
538
  }),
539
+ ...(anthropicOptions?.metadata?.userId != null && {
540
+ metadata: { user_id: anthropicOptions.metadata.userId },
541
+ }),
411
542
 
412
543
  // mcp servers:
413
544
  ...(anthropicOptions?.mcpServers &&
@@ -599,7 +730,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
599
730
  anthropicOptions.container.skills &&
600
731
  anthropicOptions.container.skills.length > 0
601
732
  ) {
602
- betas.add('code-execution-2025-08-25');
733
+ // code-execution-2025-08-25 is GA — no beta header needed
603
734
  betas.add('skills-2025-10-02');
604
735
  betas.add('files-api-2025-04-14');
605
736
 
@@ -644,6 +775,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
644
775
  disableParallelToolUse: true,
645
776
  cacheControlValidator,
646
777
  supportsStructuredOutput: false,
778
+ supportsStrictTools,
647
779
  }
648
780
  : {
649
781
  tools: tools ?? [],
@@ -651,6 +783,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
651
783
  disableParallelToolUse: anthropicOptions?.disableParallelToolUse,
652
784
  cacheControlValidator,
653
785
  supportsStructuredOutput,
786
+ supportsStrictTools,
654
787
  },
655
788
  );
656
789
 
@@ -724,7 +857,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
724
857
  return this.config.transformRequestBody?.(args, betas) ?? args;
725
858
  }
726
859
 
727
- private extractCitationDocuments(prompt: LanguageModelV3Prompt): Array<{
860
+ private extractCitationDocuments(prompt: LanguageModelV4Prompt): Array<{
728
861
  title: string;
729
862
  filename?: string;
730
863
  mediaType: string;
@@ -768,8 +901,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
768
901
  }
769
902
 
770
903
  async doGenerate(
771
- options: LanguageModelV3CallOptions,
772
- ): Promise<LanguageModelV3GenerateResult> {
904
+ options: LanguageModelV4CallOptions,
905
+ ): Promise<LanguageModelV4GenerateResult> {
773
906
  const {
774
907
  args,
775
908
  warnings,
@@ -809,8 +942,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
809
942
  fetch: this.config.fetch,
810
943
  });
811
944
 
812
- const content: Array<LanguageModelV3Content> = [];
813
- const mcpToolCalls: Record<string, LanguageModelV3ToolCall> = {};
945
+ const content: Array<LanguageModelV4Content> = [];
946
+ const mcpToolCalls: Record<string, LanguageModelV4ToolCall> = {};
814
947
  const serverToolCalls: Record<string, string> = {}; // tool_use_id -> provider tool name
815
948
  let isJsonResponseFromTool = false;
816
949
 
@@ -1084,6 +1217,20 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1084
1217
 
1085
1218
  // code execution 20250522:
1086
1219
  case 'code_execution_tool_result': {
1220
+ // When code_execution was not explicitly requested (markCodeExecutionDynamic),
1221
+ // intercept ALL results and return a clear error telling the model to use
1222
+ // web_search/web_fetch as direct tool calls instead of wrapping them in Python.
1223
+ if (markCodeExecutionDynamic) {
1224
+ content.push({
1225
+ type: 'tool-result',
1226
+ toolCallId: part.tool_use_id,
1227
+ toolName: toolNameMapping.toCustomToolName('code_execution'),
1228
+ isError: true,
1229
+ result:
1230
+ 'STOP: code_execution is disabled. Do NOT wrap web_search or web_fetch in Python code. Call web_search and web_fetch as DIRECT tool calls — they are standalone tools, not Python functions.',
1231
+ });
1232
+ break;
1233
+ }
1087
1234
  if (part.content.type === 'code_execution_result') {
1088
1235
  content.push({
1089
1236
  type: 'tool-result',
@@ -1128,6 +1275,17 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1128
1275
  // code execution 20250825:
1129
1276
  case 'bash_code_execution_tool_result':
1130
1277
  case 'text_editor_code_execution_tool_result': {
1278
+ if (markCodeExecutionDynamic) {
1279
+ content.push({
1280
+ type: 'tool-result',
1281
+ toolCallId: part.tool_use_id,
1282
+ toolName: toolNameMapping.toCustomToolName('code_execution'),
1283
+ isError: true,
1284
+ result:
1285
+ 'STOP: code_execution is disabled. Do NOT wrap web_search or web_fetch in Python code. Call web_search and web_fetch as DIRECT tool calls — they are standalone tools, not Python functions.',
1286
+ });
1287
+ break;
1288
+ }
1131
1289
  content.push({
1132
1290
  type: 'tool-result',
1133
1291
  toolCallId: part.tool_use_id,
@@ -1235,7 +1393,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1235
1393
  ) ?? null,
1236
1394
  } satisfies AnthropicMessageMetadata;
1237
1395
 
1238
- const providerMetadata: SharedV3ProviderMetadata = {
1396
+ const providerMetadata: SharedV4ProviderMetadata = {
1239
1397
  anthropic: anthropicMetadata,
1240
1398
  };
1241
1399
 
@@ -1249,8 +1407,8 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1249
1407
  }
1250
1408
 
1251
1409
  async doStream(
1252
- options: LanguageModelV3CallOptions,
1253
- ): Promise<LanguageModelV3StreamResult> {
1410
+ options: LanguageModelV4CallOptions,
1411
+ ): Promise<LanguageModelV4StreamResult> {
1254
1412
  const {
1255
1413
  args: body,
1256
1414
  warnings,
@@ -1287,7 +1445,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1287
1445
  fetch: this.config.fetch,
1288
1446
  });
1289
1447
 
1290
- let finishReason: LanguageModelV3FinishReason = {
1448
+ let finishReason: LanguageModelV4FinishReason = {
1291
1449
  unified: 'other',
1292
1450
  raw: undefined,
1293
1451
  };
@@ -1319,7 +1477,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1319
1477
  }
1320
1478
  | { type: 'text' | 'reasoning' }
1321
1479
  > = {};
1322
- const mcpToolCalls: Record<string, LanguageModelV3ToolCall> = {};
1480
+ const mcpToolCalls: Record<string, LanguageModelV4ToolCall> = {};
1323
1481
  const serverToolCalls: Record<string, string> = {}; // tool_use_id -> provider tool name
1324
1482
 
1325
1483
  let contextManagement:
@@ -1353,7 +1511,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1353
1511
  const transformedStream = response.pipeThrough(
1354
1512
  new TransformStream<
1355
1513
  ParseResult<InferSchema<typeof anthropicMessagesChunkSchema>>,
1356
- LanguageModelV3StreamPart
1514
+ LanguageModelV4StreamPart
1357
1515
  >({
1358
1516
  start(controller) {
1359
1517
  controller.enqueue({ type: 'stream-start', warnings });
@@ -1662,6 +1820,18 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1662
1820
 
1663
1821
  // code execution 20250522:
1664
1822
  case 'code_execution_tool_result': {
1823
+ if (markCodeExecutionDynamic) {
1824
+ controller.enqueue({
1825
+ type: 'tool-result',
1826
+ toolCallId: part.tool_use_id,
1827
+ toolName:
1828
+ toolNameMapping.toCustomToolName('code_execution'),
1829
+ isError: true,
1830
+ result:
1831
+ 'STOP: code_execution is disabled. Do NOT wrap web_search or web_fetch in Python code. Call web_search and web_fetch as DIRECT tool calls — they are standalone tools, not Python functions.',
1832
+ });
1833
+ return;
1834
+ }
1665
1835
  if (part.content.type === 'code_execution_result') {
1666
1836
  controller.enqueue({
1667
1837
  type: 'tool-result',
@@ -1714,6 +1884,18 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
1714
1884
  // code execution 20250825:
1715
1885
  case 'bash_code_execution_tool_result':
1716
1886
  case 'text_editor_code_execution_tool_result': {
1887
+ if (markCodeExecutionDynamic) {
1888
+ controller.enqueue({
1889
+ type: 'tool-result',
1890
+ toolCallId: part.tool_use_id,
1891
+ toolName:
1892
+ toolNameMapping.toCustomToolName('code_execution'),
1893
+ isError: true,
1894
+ result:
1895
+ 'STOP: code_execution is disabled. Do NOT wrap web_search or web_fetch in Python code. Call web_search and web_fetch as DIRECT tool calls — they are standalone tools, not Python functions.',
1896
+ });
1897
+ return;
1898
+ }
1717
1899
  controller.enqueue({
1718
1900
  type: 'tool-result',
1719
1901
  toolCallId: part.tool_use_id,
@@ -2206,7 +2388,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
2206
2388
  contextManagement,
2207
2389
  } satisfies AnthropicMessageMetadata;
2208
2390
 
2209
- const providerMetadata: SharedV3ProviderMetadata = {
2391
+ const providerMetadata: SharedV4ProviderMetadata = {
2210
2392
  anthropic: anthropicMetadata,
2211
2393
  };
2212
2394
 
@@ -2289,9 +2471,10 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
2289
2471
  * @see https://docs.claude.com/en/docs/about-claude/models/overview#model-comparison-table
2290
2472
  * @see https://platform.claude.com/docs/en/build-with-claude/structured-outputs
2291
2473
  */
2292
- function getModelCapabilities(modelId: string): {
2474
+ export function getModelCapabilities(modelId: string): {
2293
2475
  maxOutputTokens: number;
2294
2476
  supportsStructuredOutput: boolean;
2477
+ supportsAdaptiveThinking: boolean;
2295
2478
  isKnownModel: boolean;
2296
2479
  } {
2297
2480
  if (
@@ -2301,6 +2484,7 @@ function getModelCapabilities(modelId: string): {
2301
2484
  return {
2302
2485
  maxOutputTokens: 128000,
2303
2486
  supportsStructuredOutput: true,
2487
+ supportsAdaptiveThinking: true,
2304
2488
  isKnownModel: true,
2305
2489
  };
2306
2490
  } else if (
@@ -2311,36 +2495,42 @@ function getModelCapabilities(modelId: string): {
2311
2495
  return {
2312
2496
  maxOutputTokens: 64000,
2313
2497
  supportsStructuredOutput: true,
2498
+ supportsAdaptiveThinking: false,
2314
2499
  isKnownModel: true,
2315
2500
  };
2316
2501
  } else if (modelId.includes('claude-opus-4-1')) {
2317
2502
  return {
2318
2503
  maxOutputTokens: 32000,
2319
2504
  supportsStructuredOutput: true,
2505
+ supportsAdaptiveThinking: false,
2320
2506
  isKnownModel: true,
2321
2507
  };
2322
2508
  } else if (modelId.includes('claude-sonnet-4-')) {
2323
2509
  return {
2324
2510
  maxOutputTokens: 64000,
2325
2511
  supportsStructuredOutput: false,
2512
+ supportsAdaptiveThinking: false,
2326
2513
  isKnownModel: true,
2327
2514
  };
2328
2515
  } else if (modelId.includes('claude-opus-4-')) {
2329
2516
  return {
2330
2517
  maxOutputTokens: 32000,
2331
2518
  supportsStructuredOutput: false,
2519
+ supportsAdaptiveThinking: false,
2332
2520
  isKnownModel: true,
2333
2521
  };
2334
2522
  } else if (modelId.includes('claude-3-haiku')) {
2335
2523
  return {
2336
2524
  maxOutputTokens: 4096,
2337
2525
  supportsStructuredOutput: false,
2526
+ supportsAdaptiveThinking: false,
2338
2527
  isKnownModel: true,
2339
2528
  };
2340
2529
  } else {
2341
2530
  return {
2342
2531
  maxOutputTokens: 4096,
2343
2532
  supportsStructuredOutput: false,
2533
+ supportsAdaptiveThinking: false,
2344
2534
  isKnownModel: false,
2345
2535
  };
2346
2536
  }
@@ -2371,6 +2561,52 @@ function hasWebTool20260209WithoutCodeExecution(
2371
2561
  return hasWebTool20260209 && !hasCodeExecutionTool;
2372
2562
  }
2373
2563
 
2564
+ function resolveAnthropicReasoningConfig({
2565
+ reasoning,
2566
+ supportsAdaptiveThinking,
2567
+ maxOutputTokensForModel,
2568
+ warnings,
2569
+ }: {
2570
+ reasoning: LanguageModelV4CallOptions['reasoning'];
2571
+ supportsAdaptiveThinking: boolean;
2572
+ maxOutputTokensForModel: number;
2573
+ warnings: SharedV4Warning[];
2574
+ }): Pick<AnthropicLanguageModelOptions, 'thinking' | 'effort'> | undefined {
2575
+ if (!isCustomReasoning(reasoning)) {
2576
+ return undefined;
2577
+ }
2578
+
2579
+ if (reasoning === 'none') {
2580
+ return { thinking: { type: 'disabled' } };
2581
+ }
2582
+
2583
+ if (supportsAdaptiveThinking) {
2584
+ const effort = mapReasoningToProviderEffort({
2585
+ reasoning,
2586
+ effortMap: {
2587
+ minimal: 'low' as const,
2588
+ low: 'low' as const,
2589
+ medium: 'medium' as const,
2590
+ high: 'high' as const,
2591
+ xhigh: 'max' as const,
2592
+ },
2593
+ warnings,
2594
+ });
2595
+ return { thinking: { type: 'adaptive' }, effort };
2596
+ }
2597
+
2598
+ const budgetTokens = mapReasoningToProviderBudget({
2599
+ reasoning,
2600
+ maxOutputTokens: maxOutputTokensForModel,
2601
+ maxReasoningBudget: maxOutputTokensForModel,
2602
+ warnings,
2603
+ });
2604
+ if (budgetTokens == null) {
2605
+ return undefined;
2606
+ }
2607
+ return { thinking: { type: 'enabled', budgetTokens } };
2608
+ }
2609
+
2374
2610
  function mapAnthropicResponseContextManagement(
2375
2611
  contextManagement: AnthropicResponseContextManagement | null | undefined,
2376
2612
  ): AnthropicMessageMetadata['contextManagement'] | null {
@@ -124,6 +124,23 @@ export const anthropicLanguageModelOptions = z.object({
124
124
  })
125
125
  .optional(),
126
126
 
127
+ /**
128
+ * Metadata to include with the request.
129
+ *
130
+ * See https://platform.claude.com/docs/en/api/messages/create for details.
131
+ */
132
+ metadata: z
133
+ .object({
134
+ /**
135
+ * An external identifier for the user associated with the request.
136
+ *
137
+ * Should be a UUID, hash value, or other opaque identifier.
138
+ * Must not contain PII (name, email, phone number, etc.).
139
+ */
140
+ userId: z.string().optional(),
141
+ })
142
+ .optional(),
143
+
127
144
  /**
128
145
  * MCP servers to be utilized in this request.
129
146
  */
@@ -200,6 +217,13 @@ export const anthropicLanguageModelOptions = z.object({
200
217
  */
201
218
  prefill: z.string().optional(),
202
219
 
220
+ /**
221
+ * Service tier selection.
222
+ * - 'auto': Allow Anthropic to pick standard or priority based on availability.
223
+ * See https://docs.anthropic.com/en/api/messages
224
+ */
225
+ serviceTier: z.enum(['auto']).optional(),
226
+
203
227
  contextManagement: z
204
228
  .object({
205
229
  edits: z.array(