@ai-sdk/anthropic 4.0.79 → 4.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.
@@ -742,6 +742,13 @@ room for both, the provider adds `budgetTokens` to `maxOutputTokens` when
742
742
  setting `max_tokens`. For known models, the combined value is capped at the
743
743
  model's maximum output token limit.
744
744
 
745
+ With manual thinking (`thinking.type: 'enabled'`), a `required` or named
746
+ `toolChoice` falls back to `auto` with a warning. For a named tool choice, only
747
+ the selected tool is sent. This also applies when the top-level `reasoning`
748
+ option enables manual thinking, including when structured output uses the
749
+ internal JSON response tool. Tool use is no longer guaranteed: instruct the
750
+ model to use the tool in your prompt and verify that a tool call was made.
751
+
745
752
  See [AI SDK UI: Chatbot](/docs/ai-sdk-ui/chatbot#reasoning) for more details
746
753
  on how to integrate reasoning into your chatbot.
747
754
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/anthropic",
3
- "version": "4.0.79",
3
+ "version": "4.0.81",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -35,8 +35,8 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@ai-sdk/provider": "4.0.27",
39
- "@ai-sdk/provider-utils": "5.0.59"
38
+ "@ai-sdk/provider": "4.0.28",
39
+ "@ai-sdk/provider-utils": "5.0.61"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@ai-sdk/test-server": "2.0.4",
@@ -255,6 +255,12 @@ export type AnthropicLanguageModelConfig = {
255
255
  args: Record<string, any>,
256
256
  betas: Set<string>,
257
257
  ) => Record<string, any>;
258
+ transformRequestHeaders?: (
259
+ headers: Record<string, string | undefined>,
260
+ providerOptions: LanguageModelV4CallOptions['providerOptions'],
261
+ ) =>
262
+ | Record<string, string | undefined>
263
+ | PromiseLike<Record<string, string | undefined>>;
258
264
  supportedUrls?: () => LanguageModelV4['supportedUrls'];
259
265
  generateId?: () => string;
260
266
  supportsNativeStructuredOutput?: boolean;
@@ -1067,7 +1073,8 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
1067
1073
  supportsStructuredOutput: false,
1068
1074
  supportsStrictTools,
1069
1075
  defaultEagerInputStreaming,
1070
- rejectsForcedToolUse,
1076
+ rejectsForcedToolUse:
1077
+ rejectsForcedToolUse || thinkingType === 'enabled',
1071
1078
  }
1072
1079
  : {
1073
1080
  tools: tools ?? [],
@@ -1077,7 +1084,8 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
1077
1084
  supportsStructuredOutput,
1078
1085
  supportsStrictTools,
1079
1086
  defaultEagerInputStreaming,
1080
- rejectsForcedToolUse,
1087
+ rejectsForcedToolUse:
1088
+ rejectsForcedToolUse || thinkingType === 'enabled',
1081
1089
  },
1082
1090
  );
1083
1091
 
@@ -1121,15 +1129,21 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
1121
1129
  private async getHeaders({
1122
1130
  betas,
1123
1131
  headers,
1132
+ providerOptions,
1124
1133
  }: {
1125
1134
  betas: Set<string>;
1126
1135
  headers: Record<string, string | undefined> | undefined;
1136
+ providerOptions: LanguageModelV4CallOptions['providerOptions'];
1127
1137
  }) {
1128
- return combineHeaders(
1138
+ const combinedHeaders = combineHeaders(
1129
1139
  this.config.headers ? await resolve(this.config.headers) : undefined,
1130
1140
  headers,
1131
1141
  betas.size > 0 ? { 'anthropic-beta': Array.from(betas).join(',') } : {},
1132
1142
  );
1143
+
1144
+ return this.config.transformRequestHeaders
1145
+ ? this.config.transformRequestHeaders(combinedHeaders, providerOptions)
1146
+ : combinedHeaders;
1133
1147
  }
1134
1148
 
1135
1149
  private async getBetasFromHeaders(
@@ -1240,7 +1254,11 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
1240
1254
  rawValue: rawResponse,
1241
1255
  } = await postJsonToApi({
1242
1256
  url: this.buildRequestUrl(false),
1243
- headers: await this.getHeaders({ betas, headers: options.headers }),
1257
+ headers: await this.getHeaders({
1258
+ betas,
1259
+ headers: options.headers,
1260
+ providerOptions: options.providerOptions,
1261
+ }),
1244
1262
  body: this.transformRequestBody(args, betas),
1245
1263
  failedResponseHandler: anthropicFailedResponseHandler,
1246
1264
  successfulResponseHandler: createJsonResponseHandler(
@@ -1880,7 +1898,11 @@ export class AnthropicLanguageModel implements LanguageModelV4 {
1880
1898
  const url = this.buildRequestUrl(true);
1881
1899
  const { responseHeaders, value: response } = await postJsonToApi({
1882
1900
  url,
1883
- headers: await this.getHeaders({ betas, headers: options.headers }),
1901
+ headers: await this.getHeaders({
1902
+ betas,
1903
+ headers: options.headers,
1904
+ providerOptions: options.providerOptions,
1905
+ }),
1884
1906
  body: this.transformRequestBody(body, betas),
1885
1907
  failedResponseHandler: anthropicFailedResponseHandler,
1886
1908
  successfulResponseHandler:
@@ -56,9 +56,9 @@ export async function prepareTools({
56
56
  defaultEagerInputStreaming?: boolean;
57
57
 
58
58
  /**
59
- * Whether the model rejects forced tool use (`tool_choice` `any` or a
60
- * named tool). When true, `required` and `tool` tool choices fall back to
61
- * `auto` with a warning.
59
+ * Whether the model or thinking configuration rejects forced tool use
60
+ * (`tool_choice` `any` or a named tool). When true, `required` and `tool`
61
+ * tool choices fall back to `auto` with a warning.
62
62
  */
63
63
  rejectsForcedToolUse?: boolean;
64
64
  }): Promise<{
@@ -492,7 +492,7 @@ export async function prepareTools({
492
492
  type: 'unsupported',
493
493
  feature: 'toolChoice',
494
494
  details:
495
- `toolChoice 'required' is not supported by this model because it rejects forced tool use. ` +
495
+ `toolChoice 'required' is not supported with this model or thinking configuration. ` +
496
496
  `Using 'auto' instead. Instruct the model to use a tool in the prompt and verify that a tool call was made.`,
497
497
  });
498
498
  return {
@@ -527,7 +527,7 @@ export async function prepareTools({
527
527
  type: 'unsupported',
528
528
  feature: 'toolChoice',
529
529
  details:
530
- `toolChoice 'tool' is not supported by this model because it rejects forced tool use. ` +
530
+ `toolChoice 'tool' is not supported with this model or thinking configuration. ` +
531
531
  `Only the '${toolChoice.toolName}' tool is sent with 'auto' tool choice. ` +
532
532
  `Instruct the model to use the tool in the prompt and verify that a tool call was made.`,
533
533
  });
@@ -550,6 +550,31 @@ export async function convertToAnthropicPrompt({
550
550
  contentPart.mediaType,
551
551
  );
552
552
 
553
+ if (contentPart.data.type === 'reference') {
554
+ const fileId = resolveProviderReference({
555
+ reference: contentPart.data.reference,
556
+ provider: 'anthropic',
557
+ });
558
+ betas.add('files-api-2025-04-14');
559
+
560
+ if (topLevel === 'image') {
561
+ return {
562
+ type: 'image' as const,
563
+ source: {
564
+ type: 'file' as const,
565
+ file_id: fileId,
566
+ },
567
+ };
568
+ }
569
+ return {
570
+ type: 'document' as const,
571
+ source: {
572
+ type: 'file' as const,
573
+ file_id: fileId,
574
+ },
575
+ };
576
+ }
577
+
553
578
  if (contentPart.data.type === 'url') {
554
579
  if (topLevel === 'image') {
555
580
  return {