@ai-sdk/anthropic 4.0.83 → 4.0.85

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.
@@ -69,7 +69,10 @@ import {
69
69
  convertAnthropicUsage,
70
70
  type AnthropicUsage,
71
71
  } from './convert-anthropic-usage';
72
- import { convertToAnthropicPrompt } from './convert-to-anthropic-prompt';
72
+ import {
73
+ convertToAnthropicPrompt,
74
+ type AnthropicMediaPartConverter,
75
+ } from './convert-to-anthropic-prompt';
73
76
  import { CacheControlValidator } from './get-cache-control';
74
77
  import { mapAnthropicStopReason } from './map-anthropic-stop-reason';
75
78
  import { sanitizeJsonSchema } from './sanitize-json-schema';
@@ -251,6 +254,8 @@ export type AnthropicLanguageModelConfig = {
251
254
  headers?: Resolvable<Record<string, string | undefined>>;
252
255
  fetch?: FetchFunction;
253
256
  buildRequestUrl?: (baseURL: string, isStreaming: boolean) => string;
257
+ /** Custom media conversion for compatible providers; undefined uses the default. */
258
+ convertMediaPart?: AnthropicMediaPartConverter;
254
259
  transformRequestBody?: (
255
260
  args: Record<string, any>,
256
261
  betas: Set<string>,
@@ -265,6 +270,12 @@ export type AnthropicLanguageModelConfig = {
265
270
  generateId?: () => string;
266
271
  supportsNativeStructuredOutput?: boolean;
267
272
  supportsStrictTools?: boolean;
273
+ /** Maximum temperature for compatible providers. Defaults to 1. */
274
+ maxTemperature?: number;
275
+ /** Preserve temperature and topP with thinking for compatible providers. */
276
+ supportsTemperatureAndTopPWithThinking?: boolean;
277
+ /** Cache option namespace for compatible providers. Defaults to anthropic. */
278
+ cacheControlProviderOptionsName?: string;
268
279
  };
269
280
 
270
281
  export class AnthropicLanguageModel implements LanguageModelV4 {
@@ -350,18 +361,24 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
350
361
  warnings.push({ type: 'unsupported', feature: 'seed' });
351
362
  }
352
363
 
353
- if (temperature != null && temperature > 1) {
364
+ const maxTemperature = config.maxTemperature ?? 1;
365
+ const temperatureProvider =
366
+ config.maxTemperature == null
367
+ ? 'anthropic'
368
+ : getProviderOptionsName(config.provider);
369
+
370
+ if (temperature != null && temperature > maxTemperature) {
354
371
  warnings.push({
355
372
  type: 'unsupported',
356
373
  feature: 'temperature',
357
- details: `${temperature} exceeds anthropic maximum of 1.0. clamped to 1.0`,
374
+ details: `${temperature} exceeds ${temperatureProvider} maximum of ${maxTemperature.toFixed(1)}. clamped to ${maxTemperature.toFixed(1)}`,
358
375
  });
359
- temperature = 1;
376
+ temperature = maxTemperature;
360
377
  } else if (temperature != null && temperature < 0) {
361
378
  warnings.push({
362
379
  type: 'unsupported',
363
380
  feature: 'temperature',
364
- details: `${temperature} is below anthropic minimum of 0. clamped to 0`,
381
+ details: `${temperature} is below ${temperatureProvider} minimum of 0. clamped to 0`,
365
382
  });
366
383
  temperature = 0;
367
384
  }
@@ -530,7 +547,9 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
530
547
  }
531
548
 
532
549
  // Create a shared cache control validator to track breakpoints across tools and messages
533
- const cacheControlValidator = new CacheControlValidator();
550
+ const cacheControlValidator = new CacheControlValidator(
551
+ config.cacheControlProviderOptionsName,
552
+ );
534
553
 
535
554
  const toolNameMapping = createToolNameMapping({
536
555
  tools,
@@ -570,6 +589,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
570
589
  cacheControlValidator,
571
590
  toolNameMapping,
572
591
  toolsetNames,
592
+ convertMediaPart: config.convertMediaPart,
573
593
  });
574
594
 
575
595
  /*
@@ -921,7 +941,10 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
921
941
  thinkingBudget = 1024;
922
942
  }
923
943
 
924
- if (baseArgs.temperature != null) {
944
+ if (
945
+ baseArgs.temperature != null &&
946
+ !config.supportsTemperatureAndTopPWithThinking
947
+ ) {
925
948
  baseArgs.temperature = undefined;
926
949
  warnings.push({
927
950
  type: 'unsupported',
@@ -939,7 +962,7 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
939
962
  });
940
963
  }
941
964
 
942
- if (topP != null) {
965
+ if (topP != null && !config.supportsTemperatureAndTopPWithThinking) {
943
966
  baseArgs.top_p = undefined;
944
967
  warnings.push({
945
968
  type: 'unsupported',
@@ -2,6 +2,7 @@ import {
2
2
  UnsupportedFunctionalityError,
3
3
  type JSONObject,
4
4
  type JSONValue,
5
+ type LanguageModelV4FilePart,
5
6
  type SharedV4Warning,
6
7
  type LanguageModelV4Message,
7
8
  type LanguageModelV4Prompt,
@@ -21,9 +22,10 @@ import {
21
22
  type ToolNameMapping,
22
23
  } from '@ai-sdk/provider-utils';
23
24
  import {
24
- anthropicFallbackContentSchema,
25
+ anthropicFallbackContentSchemaValidator,
25
26
  anthropicReasoningMetadataSchema,
26
27
  type AnthropicAssistantMessage,
28
+ type AnthropicImageContent,
27
29
  type AnthropicPrompt,
28
30
  type AnthropicSystemMessage,
29
31
  type AnthropicTextContent,
@@ -31,6 +33,7 @@ import {
31
33
  type AnthropicToolCallCaller,
32
34
  type AnthropicToolResultContent,
33
35
  type AnthropicUserMessage,
36
+ type AnthropicVideoContent,
34
37
  type AnthropicWebFetchToolResultContent,
35
38
  type Citation,
36
39
  } from './anthropic-api';
@@ -77,6 +80,14 @@ function extractErrorValue(value: unknown): { errorCode?: string } {
77
80
  return {};
78
81
  }
79
82
 
83
+ /** Return undefined to use the default file conversion. */
84
+ export type AnthropicMediaPartConverter = (
85
+ part: LanguageModelV4FilePart,
86
+ ) => PromiseLike<
87
+ | Omit<AnthropicImageContent | AnthropicVideoContent, 'cache_control'>
88
+ | undefined
89
+ >;
90
+
80
91
  export async function convertToAnthropicPrompt({
81
92
  prompt,
82
93
  sendReasoning,
@@ -84,12 +95,14 @@ export async function convertToAnthropicPrompt({
84
95
  cacheControlValidator,
85
96
  toolNameMapping,
86
97
  toolsetNames = {},
98
+ convertMediaPart,
87
99
  }: {
88
100
  prompt: LanguageModelV4Prompt;
89
101
  sendReasoning: boolean;
90
102
  warnings: SharedV4Warning[];
91
103
  cacheControlValidator?: CacheControlValidator;
92
104
  toolNameMapping: ToolNameMapping;
105
+ convertMediaPart?: AnthropicMediaPartConverter;
93
106
 
94
107
  /**
95
108
  * Maps custom tool names of toolset tools (e.g. the computer toolset) to
@@ -329,6 +342,15 @@ export async function convertToAnthropicPrompt({
329
342
  }
330
343
 
331
344
  case 'file': {
345
+ const convertedPart = await convertMediaPart?.(part);
346
+ if (convertedPart != null) {
347
+ anthropicContent.push({
348
+ ...convertedPart,
349
+ cache_control: cacheControl,
350
+ });
351
+ break;
352
+ }
353
+
332
354
  switch (part.data.type) {
333
355
  case 'reference': {
334
356
  const fileId = resolveProviderReference({
@@ -858,7 +880,7 @@ export async function convertToAnthropicPrompt({
858
880
 
859
881
  const fallbackMetadata = await safeValidateTypes({
860
882
  value: part.providerOptions?.anthropic,
861
- schema: anthropicFallbackContentSchema,
883
+ schema: anthropicFallbackContentSchemaValidator,
862
884
  });
863
885
 
864
886
  if (!fallbackMetadata.success) {
@@ -11,11 +11,18 @@ const MAX_CACHE_BREAKPOINTS = 4;
11
11
  // Allows both cacheControl and cache_control for flexibility
12
12
  function getCacheControl(
13
13
  providerMetadata: SharedV4ProviderMetadata | undefined,
14
+ providerOptionsName: string,
14
15
  ): AnthropicCacheControl | undefined {
16
+ const custom = providerMetadata?.[providerOptionsName];
15
17
  const anthropic = providerMetadata?.anthropic;
16
18
 
17
- // allow both cacheControl and cache_control:
18
- const cacheControlValue = anthropic?.cacheControl ?? anthropic?.cache_control;
19
+ // Prefer the configured namespace, retaining the canonical namespace as a fallback.
20
+ // Allow both cacheControl and cache_control.
21
+ const cacheControlValue =
22
+ custom?.cacheControl ??
23
+ custom?.cache_control ??
24
+ anthropic?.cacheControl ??
25
+ anthropic?.cache_control;
19
26
 
20
27
  // Pass through value assuming it is of the correct type.
21
28
  // The Anthropic API will validate the value.
@@ -26,11 +33,16 @@ export class CacheControlValidator {
26
33
  private breakpointCount = 0;
27
34
  private warnings: SharedV4Warning[] = [];
28
35
 
36
+ constructor(private readonly providerOptionsName = 'anthropic') {}
37
+
29
38
  getCacheControl(
30
39
  providerMetadata: SharedV4ProviderMetadata | undefined,
31
40
  context: { type: string; canCache: boolean },
32
41
  ): AnthropicCacheControl | undefined {
33
- const cacheControlValue = getCacheControl(providerMetadata);
42
+ const cacheControlValue = getCacheControl(
43
+ providerMetadata,
44
+ this.providerOptionsName,
45
+ );
34
46
 
35
47
  if (!cacheControlValue) {
36
48
  return undefined;
@@ -3,6 +3,7 @@ import {
3
3
  combineHeaders,
4
4
  convertInlineFileDataToUint8Array,
5
5
  createJsonResponseHandler,
6
+ encodePathSegment,
6
7
  getFromApi,
7
8
  postFormDataToApi,
8
9
  resolve,
@@ -22,17 +23,6 @@ interface AnthropicSkillsConfig {
22
23
  fetch?: FetchFunction;
23
24
  }
24
25
 
25
- function encodePathSegment(value: string): string {
26
- const encodedValue = encodeURIComponent(value);
27
-
28
- // URL parsing normalizes both literal and percent-encoded dot segments.
29
- return encodedValue === '.'
30
- ? '%252E'
31
- : encodedValue === '..'
32
- ? '%252E%252E'
33
- : encodedValue;
34
- }
35
-
36
26
  export class AnthropicSkills implements SkillsV4 {
37
27
  readonly specificationVersion = 'v4';
38
28