@ai-sdk/anthropic 2.0.0-alpha.1 → 2.0.0-alpha.10

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.
@@ -47,6 +47,13 @@ var anthropicFailedResponseHandler = (0, import_provider_utils.createJsonErrorRe
47
47
 
48
48
  // src/anthropic-messages-options.ts
49
49
  var import_zod2 = require("zod");
50
+ var webSearchLocationSchema = import_zod2.z.object({
51
+ type: import_zod2.z.literal("approximate"),
52
+ city: import_zod2.z.string().optional(),
53
+ region: import_zod2.z.string().optional(),
54
+ country: import_zod2.z.string(),
55
+ timezone: import_zod2.z.string().optional()
56
+ });
50
57
  var anthropicProviderOptions = import_zod2.z.object({
51
58
  /**
52
59
  Include reasoning content in requests sent to the model. Defaults to `true`.
@@ -57,11 +64,39 @@ var anthropicProviderOptions = import_zod2.z.object({
57
64
  thinking: import_zod2.z.object({
58
65
  type: import_zod2.z.union([import_zod2.z.literal("enabled"), import_zod2.z.literal("disabled")]),
59
66
  budgetTokens: import_zod2.z.number().optional()
67
+ }).optional(),
68
+ /**
69
+ * Web search tool configuration for Claude models that support it.
70
+ * When provided, automatically adds the web search tool to the request.
71
+ */
72
+ webSearch: import_zod2.z.object({
73
+ /**
74
+ * Limit the number of searches per request (optional)
75
+ * Defaults to 5 if not specified
76
+ */
77
+ maxUses: import_zod2.z.number().min(1).max(20).optional(),
78
+ /**
79
+ * Only include results from these domains (optional)
80
+ * Cannot be used with blockedDomains
81
+ */
82
+ allowedDomains: import_zod2.z.array(import_zod2.z.string()).optional(),
83
+ /**
84
+ * Never include results from these domains (optional)
85
+ * Cannot be used with allowedDomains
86
+ */
87
+ blockedDomains: import_zod2.z.array(import_zod2.z.string()).optional(),
88
+ /**
89
+ * Localize search results based on user location (optional)
90
+ */
91
+ userLocation: webSearchLocationSchema.optional()
60
92
  }).optional()
61
93
  });
62
94
 
63
95
  // src/anthropic-prepare-tools.ts
64
96
  var import_provider = require("@ai-sdk/provider");
97
+ function isWebSearchTool(tool) {
98
+ return typeof tool === "object" && tool !== null && "type" in tool && tool.type === "web_search_20250305";
99
+ }
65
100
  function prepareTools({
66
101
  tools,
67
102
  toolChoice
@@ -74,6 +109,10 @@ function prepareTools({
74
109
  }
75
110
  const anthropicTools2 = [];
76
111
  for (const tool of tools) {
112
+ if (isWebSearchTool(tool)) {
113
+ anthropicTools2.push(tool);
114
+ continue;
115
+ }
77
116
  switch (tool.type) {
78
117
  case "function":
79
118
  anthropicTools2.push({
@@ -464,13 +503,16 @@ function groupIntoBlocks(prompt) {
464
503
  }
465
504
 
466
505
  // src/map-anthropic-stop-reason.ts
467
- function mapAnthropicStopReason(finishReason) {
506
+ function mapAnthropicStopReason({
507
+ finishReason,
508
+ isJsonResponseFromTool
509
+ }) {
468
510
  switch (finishReason) {
469
511
  case "end_turn":
470
512
  case "stop_sequence":
471
513
  return "stop";
472
514
  case "tool_use":
473
- return "tool-calls";
515
+ return isJsonResponseFromTool ? "stop" : "tool-calls";
474
516
  case "max_tokens":
475
517
  return "length";
476
518
  default:
@@ -482,8 +524,10 @@ function mapAnthropicStopReason(finishReason) {
482
524
  var AnthropicMessagesLanguageModel = class {
483
525
  constructor(modelId, config) {
484
526
  this.specificationVersion = "v2";
527
+ var _a;
485
528
  this.modelId = modelId;
486
529
  this.config = config;
530
+ this.generateId = (_a = config.generateId) != null ? _a : import_provider_utils3.generateId;
487
531
  }
488
532
  supportsUrl(url) {
489
533
  return url.protocol === "https:";
@@ -531,13 +575,27 @@ var AnthropicMessagesLanguageModel = class {
531
575
  setting: "seed"
532
576
  });
533
577
  }
534
- if (responseFormat != null && responseFormat.type !== "text") {
535
- warnings.push({
536
- type: "unsupported-setting",
537
- setting: "responseFormat",
538
- details: "JSON response format is not supported."
539
- });
578
+ if ((responseFormat == null ? void 0 : responseFormat.type) === "json") {
579
+ if (responseFormat.schema == null) {
580
+ warnings.push({
581
+ type: "unsupported-setting",
582
+ setting: "responseFormat",
583
+ details: "JSON response format requires a schema. The response format is ignored."
584
+ });
585
+ } else if (tools != null) {
586
+ warnings.push({
587
+ type: "unsupported-setting",
588
+ setting: "tools",
589
+ details: "JSON response format does not support tools. The provided tools are ignored."
590
+ });
591
+ }
540
592
  }
593
+ const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null ? {
594
+ type: "function",
595
+ name: "json",
596
+ description: "Respond with a JSON object.",
597
+ parameters: responseFormat.schema
598
+ } : void 0;
541
599
  const anthropicOptions = await (0, import_provider_utils3.parseProviderOptions)({
542
600
  provider: "anthropic",
543
601
  providerOptions,
@@ -599,12 +657,38 @@ var AnthropicMessagesLanguageModel = class {
599
657
  }
600
658
  baseArgs.max_tokens = maxOutputTokens + thinkingBudget;
601
659
  }
660
+ let modifiedTools = tools;
661
+ let modifiedToolChoice = toolChoice;
662
+ if (anthropicOptions == null ? void 0 : anthropicOptions.webSearch) {
663
+ const webSearchTool = {
664
+ type: "web_search_20250305",
665
+ name: "web_search",
666
+ max_uses: anthropicOptions.webSearch.maxUses,
667
+ allowed_domains: anthropicOptions.webSearch.allowedDomains,
668
+ blocked_domains: anthropicOptions.webSearch.blockedDomains,
669
+ ...anthropicOptions.webSearch.userLocation && {
670
+ user_location: {
671
+ type: anthropicOptions.webSearch.userLocation.type,
672
+ country: anthropicOptions.webSearch.userLocation.country,
673
+ city: anthropicOptions.webSearch.userLocation.city,
674
+ region: anthropicOptions.webSearch.userLocation.region,
675
+ timezone: anthropicOptions.webSearch.userLocation.timezone
676
+ }
677
+ }
678
+ };
679
+ modifiedTools = tools ? [...tools, webSearchTool] : [webSearchTool];
680
+ }
602
681
  const {
603
682
  tools: anthropicTools2,
604
683
  toolChoice: anthropicToolChoice,
605
684
  toolWarnings,
606
685
  betas: toolsBetas
607
- } = prepareTools({ tools, toolChoice });
686
+ } = prepareTools(
687
+ jsonResponseTool != null ? {
688
+ tools: [jsonResponseTool],
689
+ toolChoice: { type: "tool", toolName: jsonResponseTool.name }
690
+ } : { tools: modifiedTools, toolChoice: modifiedToolChoice }
691
+ );
608
692
  return {
609
693
  args: {
610
694
  ...baseArgs,
@@ -612,7 +696,8 @@ var AnthropicMessagesLanguageModel = class {
612
696
  tool_choice: anthropicToolChoice
613
697
  },
614
698
  warnings: [...warnings, ...toolWarnings],
615
- betas: /* @__PURE__ */ new Set([...messagesBetas, ...toolsBetas])
699
+ betas: /* @__PURE__ */ new Set([...messagesBetas, ...toolsBetas]),
700
+ jsonResponseTool
616
701
  };
617
702
  }
618
703
  async getHeaders({
@@ -634,8 +719,8 @@ var AnthropicMessagesLanguageModel = class {
634
719
  return (_c = (_b = (_a = this.config).transformRequestBody) == null ? void 0 : _b.call(_a, args)) != null ? _c : args;
635
720
  }
636
721
  async doGenerate(options) {
637
- var _a, _b, _c, _d;
638
- const { args, warnings, betas } = await this.getArgs(options);
722
+ var _a, _b, _c, _d, _e;
723
+ const { args, warnings, betas, jsonResponseTool } = await this.getArgs(options);
639
724
  const {
640
725
  responseHeaders,
641
726
  value: response,
@@ -655,7 +740,9 @@ var AnthropicMessagesLanguageModel = class {
655
740
  for (const part of response.content) {
656
741
  switch (part.type) {
657
742
  case "text": {
658
- content.push({ type: "text", text: part.text });
743
+ if (jsonResponseTool == null) {
744
+ content.push({ type: "text", text: part.text });
745
+ }
659
746
  break;
660
747
  }
661
748
  case "thinking": {
@@ -683,43 +770,84 @@ var AnthropicMessagesLanguageModel = class {
683
770
  break;
684
771
  }
685
772
  case "tool_use": {
686
- content.push({
687
- type: "tool-call",
688
- toolCallType: "function",
689
- toolCallId: part.id,
690
- toolName: part.name,
691
- args: JSON.stringify(part.input)
692
- });
773
+ content.push(
774
+ // when a json response tool is used, the tool call becomes the text:
775
+ jsonResponseTool != null ? {
776
+ type: "text",
777
+ text: JSON.stringify(part.input)
778
+ } : {
779
+ type: "tool-call",
780
+ toolCallType: "function",
781
+ toolCallId: part.id,
782
+ toolName: part.name,
783
+ args: JSON.stringify(part.input)
784
+ }
785
+ );
786
+ break;
787
+ }
788
+ case "server_tool_use": {
789
+ continue;
790
+ }
791
+ case "web_search_tool_result": {
792
+ if (Array.isArray(part.content)) {
793
+ for (const result of part.content) {
794
+ if (result.type === "web_search_result") {
795
+ content.push({
796
+ type: "source",
797
+ sourceType: "url",
798
+ id: this.generateId(),
799
+ url: result.url,
800
+ title: result.title,
801
+ providerMetadata: {
802
+ anthropic: {
803
+ encryptedContent: result.encrypted_content,
804
+ pageAge: (_a = result.page_age) != null ? _a : null
805
+ }
806
+ }
807
+ });
808
+ }
809
+ }
810
+ } else if (part.content.type === "web_search_tool_result_error") {
811
+ throw new import_provider3.APICallError({
812
+ message: `Web search failed: ${part.content.error_code}`,
813
+ url: "web_search_api",
814
+ requestBodyValues: { tool_use_id: part.tool_use_id },
815
+ data: { error_code: part.content.error_code }
816
+ });
817
+ }
693
818
  break;
694
819
  }
695
820
  }
696
821
  }
697
822
  return {
698
823
  content,
699
- finishReason: mapAnthropicStopReason(response.stop_reason),
824
+ finishReason: mapAnthropicStopReason({
825
+ finishReason: response.stop_reason,
826
+ isJsonResponseFromTool: jsonResponseTool != null
827
+ }),
700
828
  usage: {
701
829
  inputTokens: response.usage.input_tokens,
702
830
  outputTokens: response.usage.output_tokens,
703
831
  totalTokens: response.usage.input_tokens + response.usage.output_tokens,
704
- cachedInputTokens: (_a = response.usage.cache_read_input_tokens) != null ? _a : void 0
832
+ cachedInputTokens: (_b = response.usage.cache_read_input_tokens) != null ? _b : void 0
705
833
  },
706
834
  request: { body: args },
707
835
  response: {
708
- id: (_b = response.id) != null ? _b : void 0,
709
- modelId: (_c = response.model) != null ? _c : void 0,
836
+ id: (_c = response.id) != null ? _c : void 0,
837
+ modelId: (_d = response.model) != null ? _d : void 0,
710
838
  headers: responseHeaders,
711
839
  body: rawResponse
712
840
  },
713
841
  warnings,
714
842
  providerMetadata: {
715
843
  anthropic: {
716
- cacheCreationInputTokens: (_d = response.usage.cache_creation_input_tokens) != null ? _d : null
844
+ cacheCreationInputTokens: (_e = response.usage.cache_creation_input_tokens) != null ? _e : null
717
845
  }
718
846
  }
719
847
  };
720
848
  }
721
849
  async doStream(options) {
722
- const { args, warnings, betas } = await this.getArgs(options);
850
+ const { args, warnings, betas, jsonResponseTool } = await this.getArgs(options);
723
851
  const body = { ...args, stream: true };
724
852
  const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({
725
853
  url: this.buildRequestUrl(true),
@@ -741,6 +869,8 @@ var AnthropicMessagesLanguageModel = class {
741
869
  const toolCallContentBlocks = {};
742
870
  let providerMetadata = void 0;
743
871
  let blockType = void 0;
872
+ const config = this.config;
873
+ const generateId2 = this.generateId;
744
874
  return {
745
875
  stream: response.pipeThrough(
746
876
  new TransformStream({
@@ -748,7 +878,7 @@ var AnthropicMessagesLanguageModel = class {
748
878
  controller.enqueue({ type: "stream-start", warnings });
749
879
  },
750
880
  transform(chunk, controller) {
751
- var _a, _b, _c, _d, _e, _f;
881
+ var _a, _b, _c, _d, _e, _f, _g;
752
882
  if (!chunk.success) {
753
883
  controller.enqueue({ type: "error", error: chunk.error });
754
884
  return;
@@ -787,6 +917,40 @@ var AnthropicMessagesLanguageModel = class {
787
917
  };
788
918
  return;
789
919
  }
920
+ case "server_tool_use": {
921
+ return;
922
+ }
923
+ case "web_search_tool_result": {
924
+ if (Array.isArray(value.content_block.content)) {
925
+ for (const result of value.content_block.content) {
926
+ if (result.type === "web_search_result") {
927
+ controller.enqueue({
928
+ type: "source",
929
+ sourceType: "url",
930
+ id: generateId2(),
931
+ url: result.url,
932
+ title: result.title,
933
+ providerMetadata: {
934
+ anthropic: {
935
+ encryptedContent: result.encrypted_content,
936
+ pageAge: (_a = result.page_age) != null ? _a : null
937
+ }
938
+ }
939
+ });
940
+ }
941
+ }
942
+ } else if (value.content_block.content.type === "web_search_tool_result_error") {
943
+ controller.enqueue({
944
+ type: "error",
945
+ error: {
946
+ type: "web-search-error",
947
+ message: `Web search failed: ${value.content_block.content.error_code}`,
948
+ code: value.content_block.content.error_code
949
+ }
950
+ });
951
+ }
952
+ return;
953
+ }
790
954
  default: {
791
955
  const _exhaustiveCheck = contentBlockType;
792
956
  throw new Error(
@@ -798,13 +962,15 @@ var AnthropicMessagesLanguageModel = class {
798
962
  case "content_block_stop": {
799
963
  if (toolCallContentBlocks[value.index] != null) {
800
964
  const contentBlock = toolCallContentBlocks[value.index];
801
- controller.enqueue({
802
- type: "tool-call",
803
- toolCallType: "function",
804
- toolCallId: contentBlock.toolCallId,
805
- toolName: contentBlock.toolName,
806
- args: contentBlock.jsonText
807
- });
965
+ if (jsonResponseTool == null) {
966
+ controller.enqueue({
967
+ type: "tool-call",
968
+ toolCallType: "function",
969
+ toolCallId: contentBlock.toolCallId,
970
+ toolName: contentBlock.toolName,
971
+ args: contentBlock.jsonText
972
+ });
973
+ }
808
974
  delete toolCallContentBlocks[value.index];
809
975
  }
810
976
  blockType = void 0;
@@ -814,6 +980,9 @@ var AnthropicMessagesLanguageModel = class {
814
980
  const deltaType = value.delta.type;
815
981
  switch (deltaType) {
816
982
  case "text_delta": {
983
+ if (jsonResponseTool != null) {
984
+ return;
985
+ }
817
986
  controller.enqueue({
818
987
  type: "text",
819
988
  text: value.delta.text
@@ -844,16 +1013,27 @@ var AnthropicMessagesLanguageModel = class {
844
1013
  }
845
1014
  case "input_json_delta": {
846
1015
  const contentBlock = toolCallContentBlocks[value.index];
847
- controller.enqueue({
848
- type: "tool-call-delta",
849
- toolCallType: "function",
850
- toolCallId: contentBlock.toolCallId,
851
- toolName: contentBlock.toolName,
852
- argsTextDelta: value.delta.partial_json
853
- });
1016
+ if (!contentBlock) {
1017
+ return;
1018
+ }
1019
+ controller.enqueue(
1020
+ jsonResponseTool != null ? {
1021
+ type: "text",
1022
+ text: value.delta.partial_json
1023
+ } : {
1024
+ type: "tool-call-delta",
1025
+ toolCallType: "function",
1026
+ toolCallId: contentBlock.toolCallId,
1027
+ toolName: contentBlock.toolName,
1028
+ argsTextDelta: value.delta.partial_json
1029
+ }
1030
+ );
854
1031
  contentBlock.jsonText += value.delta.partial_json;
855
1032
  return;
856
1033
  }
1034
+ case "citations_delta": {
1035
+ return;
1036
+ }
857
1037
  default: {
858
1038
  const _exhaustiveCheck = deltaType;
859
1039
  throw new Error(
@@ -864,23 +1044,26 @@ var AnthropicMessagesLanguageModel = class {
864
1044
  }
865
1045
  case "message_start": {
866
1046
  usage.inputTokens = value.message.usage.input_tokens;
867
- usage.cachedInputTokens = (_a = value.message.usage.cache_read_input_tokens) != null ? _a : void 0;
1047
+ usage.cachedInputTokens = (_b = value.message.usage.cache_read_input_tokens) != null ? _b : void 0;
868
1048
  providerMetadata = {
869
1049
  anthropic: {
870
- cacheCreationInputTokens: (_b = value.message.usage.cache_creation_input_tokens) != null ? _b : null
1050
+ cacheCreationInputTokens: (_c = value.message.usage.cache_creation_input_tokens) != null ? _c : null
871
1051
  }
872
1052
  };
873
1053
  controller.enqueue({
874
1054
  type: "response-metadata",
875
- id: (_c = value.message.id) != null ? _c : void 0,
876
- modelId: (_d = value.message.model) != null ? _d : void 0
1055
+ id: (_d = value.message.id) != null ? _d : void 0,
1056
+ modelId: (_e = value.message.model) != null ? _e : void 0
877
1057
  });
878
1058
  return;
879
1059
  }
880
1060
  case "message_delta": {
881
1061
  usage.outputTokens = value.usage.output_tokens;
882
- usage.totalTokens = ((_e = usage.inputTokens) != null ? _e : 0) + ((_f = value.usage.output_tokens) != null ? _f : 0);
883
- finishReason = mapAnthropicStopReason(value.delta.stop_reason);
1062
+ usage.totalTokens = ((_f = usage.inputTokens) != null ? _f : 0) + ((_g = value.usage.output_tokens) != null ? _g : 0);
1063
+ finishReason = mapAnthropicStopReason({
1064
+ finishReason: value.delta.stop_reason,
1065
+ isJsonResponseFromTool: jsonResponseTool != null
1066
+ });
884
1067
  return;
885
1068
  }
886
1069
  case "message_stop": {
@@ -933,6 +1116,31 @@ var anthropicMessagesResponseSchema = import_zod3.z.object({
933
1116
  id: import_zod3.z.string(),
934
1117
  name: import_zod3.z.string(),
935
1118
  input: import_zod3.z.unknown()
1119
+ }),
1120
+ import_zod3.z.object({
1121
+ type: import_zod3.z.literal("server_tool_use"),
1122
+ id: import_zod3.z.string(),
1123
+ name: import_zod3.z.string(),
1124
+ input: import_zod3.z.record(import_zod3.z.unknown()).nullish()
1125
+ }),
1126
+ import_zod3.z.object({
1127
+ type: import_zod3.z.literal("web_search_tool_result"),
1128
+ tool_use_id: import_zod3.z.string(),
1129
+ content: import_zod3.z.union([
1130
+ import_zod3.z.array(
1131
+ import_zod3.z.object({
1132
+ type: import_zod3.z.literal("web_search_result"),
1133
+ url: import_zod3.z.string(),
1134
+ title: import_zod3.z.string(),
1135
+ encrypted_content: import_zod3.z.string(),
1136
+ page_age: import_zod3.z.string().nullish()
1137
+ })
1138
+ ),
1139
+ import_zod3.z.object({
1140
+ type: import_zod3.z.literal("web_search_tool_result_error"),
1141
+ error_code: import_zod3.z.string()
1142
+ })
1143
+ ])
936
1144
  })
937
1145
  ])
938
1146
  ),
@@ -941,7 +1149,10 @@ var anthropicMessagesResponseSchema = import_zod3.z.object({
941
1149
  input_tokens: import_zod3.z.number(),
942
1150
  output_tokens: import_zod3.z.number(),
943
1151
  cache_creation_input_tokens: import_zod3.z.number().nullish(),
944
- cache_read_input_tokens: import_zod3.z.number().nullish()
1152
+ cache_read_input_tokens: import_zod3.z.number().nullish(),
1153
+ server_tool_use: import_zod3.z.object({
1154
+ web_search_requests: import_zod3.z.number()
1155
+ }).nullish()
945
1156
  })
946
1157
  });
947
1158
  var anthropicMessagesChunkSchema = import_zod3.z.discriminatedUnion("type", [
@@ -978,6 +1189,31 @@ var anthropicMessagesChunkSchema = import_zod3.z.discriminatedUnion("type", [
978
1189
  import_zod3.z.object({
979
1190
  type: import_zod3.z.literal("redacted_thinking"),
980
1191
  data: import_zod3.z.string()
1192
+ }),
1193
+ import_zod3.z.object({
1194
+ type: import_zod3.z.literal("server_tool_use"),
1195
+ id: import_zod3.z.string(),
1196
+ name: import_zod3.z.string(),
1197
+ input: import_zod3.z.record(import_zod3.z.unknown()).nullish()
1198
+ }),
1199
+ import_zod3.z.object({
1200
+ type: import_zod3.z.literal("web_search_tool_result"),
1201
+ tool_use_id: import_zod3.z.string(),
1202
+ content: import_zod3.z.union([
1203
+ import_zod3.z.array(
1204
+ import_zod3.z.object({
1205
+ type: import_zod3.z.literal("web_search_result"),
1206
+ url: import_zod3.z.string(),
1207
+ title: import_zod3.z.string(),
1208
+ encrypted_content: import_zod3.z.string(),
1209
+ page_age: import_zod3.z.string().nullish()
1210
+ })
1211
+ ),
1212
+ import_zod3.z.object({
1213
+ type: import_zod3.z.literal("web_search_tool_result_error"),
1214
+ error_code: import_zod3.z.string()
1215
+ })
1216
+ ])
981
1217
  })
982
1218
  ])
983
1219
  }),
@@ -1000,6 +1236,16 @@ var anthropicMessagesChunkSchema = import_zod3.z.discriminatedUnion("type", [
1000
1236
  import_zod3.z.object({
1001
1237
  type: import_zod3.z.literal("signature_delta"),
1002
1238
  signature: import_zod3.z.string()
1239
+ }),
1240
+ import_zod3.z.object({
1241
+ type: import_zod3.z.literal("citations_delta"),
1242
+ citation: import_zod3.z.object({
1243
+ type: import_zod3.z.literal("web_search_result_location"),
1244
+ cited_text: import_zod3.z.string(),
1245
+ url: import_zod3.z.string(),
1246
+ title: import_zod3.z.string(),
1247
+ encrypted_index: import_zod3.z.string()
1248
+ })
1003
1249
  })
1004
1250
  ])
1005
1251
  }),