@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.
@@ -1,11 +1,13 @@
1
1
  // src/anthropic-messages-language-model.ts
2
2
  import {
3
+ APICallError,
3
4
  UnsupportedFunctionalityError as UnsupportedFunctionalityError3
4
5
  } from "@ai-sdk/provider";
5
6
  import {
6
7
  combineHeaders,
7
8
  createEventSourceResponseHandler,
8
9
  createJsonResponseHandler,
10
+ generateId,
9
11
  parseProviderOptions as parseProviderOptions2,
10
12
  postJsonToApi,
11
13
  resolve
@@ -29,6 +31,13 @@ var anthropicFailedResponseHandler = createJsonErrorResponseHandler({
29
31
 
30
32
  // src/anthropic-messages-options.ts
31
33
  import { z as z2 } from "zod";
34
+ var webSearchLocationSchema = z2.object({
35
+ type: z2.literal("approximate"),
36
+ city: z2.string().optional(),
37
+ region: z2.string().optional(),
38
+ country: z2.string(),
39
+ timezone: z2.string().optional()
40
+ });
32
41
  var anthropicProviderOptions = z2.object({
33
42
  /**
34
43
  Include reasoning content in requests sent to the model. Defaults to `true`.
@@ -39,6 +48,31 @@ var anthropicProviderOptions = z2.object({
39
48
  thinking: z2.object({
40
49
  type: z2.union([z2.literal("enabled"), z2.literal("disabled")]),
41
50
  budgetTokens: z2.number().optional()
51
+ }).optional(),
52
+ /**
53
+ * Web search tool configuration for Claude models that support it.
54
+ * When provided, automatically adds the web search tool to the request.
55
+ */
56
+ webSearch: z2.object({
57
+ /**
58
+ * Limit the number of searches per request (optional)
59
+ * Defaults to 5 if not specified
60
+ */
61
+ maxUses: z2.number().min(1).max(20).optional(),
62
+ /**
63
+ * Only include results from these domains (optional)
64
+ * Cannot be used with blockedDomains
65
+ */
66
+ allowedDomains: z2.array(z2.string()).optional(),
67
+ /**
68
+ * Never include results from these domains (optional)
69
+ * Cannot be used with allowedDomains
70
+ */
71
+ blockedDomains: z2.array(z2.string()).optional(),
72
+ /**
73
+ * Localize search results based on user location (optional)
74
+ */
75
+ userLocation: webSearchLocationSchema.optional()
42
76
  }).optional()
43
77
  });
44
78
 
@@ -46,6 +80,9 @@ var anthropicProviderOptions = z2.object({
46
80
  import {
47
81
  UnsupportedFunctionalityError
48
82
  } from "@ai-sdk/provider";
83
+ function isWebSearchTool(tool) {
84
+ return typeof tool === "object" && tool !== null && "type" in tool && tool.type === "web_search_20250305";
85
+ }
49
86
  function prepareTools({
50
87
  tools,
51
88
  toolChoice
@@ -58,6 +95,10 @@ function prepareTools({
58
95
  }
59
96
  const anthropicTools2 = [];
60
97
  for (const tool of tools) {
98
+ if (isWebSearchTool(tool)) {
99
+ anthropicTools2.push(tool);
100
+ continue;
101
+ }
61
102
  switch (tool.type) {
62
103
  case "function":
63
104
  anthropicTools2.push({
@@ -450,13 +491,16 @@ function groupIntoBlocks(prompt) {
450
491
  }
451
492
 
452
493
  // src/map-anthropic-stop-reason.ts
453
- function mapAnthropicStopReason(finishReason) {
494
+ function mapAnthropicStopReason({
495
+ finishReason,
496
+ isJsonResponseFromTool
497
+ }) {
454
498
  switch (finishReason) {
455
499
  case "end_turn":
456
500
  case "stop_sequence":
457
501
  return "stop";
458
502
  case "tool_use":
459
- return "tool-calls";
503
+ return isJsonResponseFromTool ? "stop" : "tool-calls";
460
504
  case "max_tokens":
461
505
  return "length";
462
506
  default:
@@ -468,8 +512,10 @@ function mapAnthropicStopReason(finishReason) {
468
512
  var AnthropicMessagesLanguageModel = class {
469
513
  constructor(modelId, config) {
470
514
  this.specificationVersion = "v2";
515
+ var _a;
471
516
  this.modelId = modelId;
472
517
  this.config = config;
518
+ this.generateId = (_a = config.generateId) != null ? _a : generateId;
473
519
  }
474
520
  supportsUrl(url) {
475
521
  return url.protocol === "https:";
@@ -517,13 +563,27 @@ var AnthropicMessagesLanguageModel = class {
517
563
  setting: "seed"
518
564
  });
519
565
  }
520
- if (responseFormat != null && responseFormat.type !== "text") {
521
- warnings.push({
522
- type: "unsupported-setting",
523
- setting: "responseFormat",
524
- details: "JSON response format is not supported."
525
- });
566
+ if ((responseFormat == null ? void 0 : responseFormat.type) === "json") {
567
+ if (responseFormat.schema == null) {
568
+ warnings.push({
569
+ type: "unsupported-setting",
570
+ setting: "responseFormat",
571
+ details: "JSON response format requires a schema. The response format is ignored."
572
+ });
573
+ } else if (tools != null) {
574
+ warnings.push({
575
+ type: "unsupported-setting",
576
+ setting: "tools",
577
+ details: "JSON response format does not support tools. The provided tools are ignored."
578
+ });
579
+ }
526
580
  }
581
+ const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null ? {
582
+ type: "function",
583
+ name: "json",
584
+ description: "Respond with a JSON object.",
585
+ parameters: responseFormat.schema
586
+ } : void 0;
527
587
  const anthropicOptions = await parseProviderOptions2({
528
588
  provider: "anthropic",
529
589
  providerOptions,
@@ -585,12 +645,38 @@ var AnthropicMessagesLanguageModel = class {
585
645
  }
586
646
  baseArgs.max_tokens = maxOutputTokens + thinkingBudget;
587
647
  }
648
+ let modifiedTools = tools;
649
+ let modifiedToolChoice = toolChoice;
650
+ if (anthropicOptions == null ? void 0 : anthropicOptions.webSearch) {
651
+ const webSearchTool = {
652
+ type: "web_search_20250305",
653
+ name: "web_search",
654
+ max_uses: anthropicOptions.webSearch.maxUses,
655
+ allowed_domains: anthropicOptions.webSearch.allowedDomains,
656
+ blocked_domains: anthropicOptions.webSearch.blockedDomains,
657
+ ...anthropicOptions.webSearch.userLocation && {
658
+ user_location: {
659
+ type: anthropicOptions.webSearch.userLocation.type,
660
+ country: anthropicOptions.webSearch.userLocation.country,
661
+ city: anthropicOptions.webSearch.userLocation.city,
662
+ region: anthropicOptions.webSearch.userLocation.region,
663
+ timezone: anthropicOptions.webSearch.userLocation.timezone
664
+ }
665
+ }
666
+ };
667
+ modifiedTools = tools ? [...tools, webSearchTool] : [webSearchTool];
668
+ }
588
669
  const {
589
670
  tools: anthropicTools2,
590
671
  toolChoice: anthropicToolChoice,
591
672
  toolWarnings,
592
673
  betas: toolsBetas
593
- } = prepareTools({ tools, toolChoice });
674
+ } = prepareTools(
675
+ jsonResponseTool != null ? {
676
+ tools: [jsonResponseTool],
677
+ toolChoice: { type: "tool", toolName: jsonResponseTool.name }
678
+ } : { tools: modifiedTools, toolChoice: modifiedToolChoice }
679
+ );
594
680
  return {
595
681
  args: {
596
682
  ...baseArgs,
@@ -598,7 +684,8 @@ var AnthropicMessagesLanguageModel = class {
598
684
  tool_choice: anthropicToolChoice
599
685
  },
600
686
  warnings: [...warnings, ...toolWarnings],
601
- betas: /* @__PURE__ */ new Set([...messagesBetas, ...toolsBetas])
687
+ betas: /* @__PURE__ */ new Set([...messagesBetas, ...toolsBetas]),
688
+ jsonResponseTool
602
689
  };
603
690
  }
604
691
  async getHeaders({
@@ -620,8 +707,8 @@ var AnthropicMessagesLanguageModel = class {
620
707
  return (_c = (_b = (_a = this.config).transformRequestBody) == null ? void 0 : _b.call(_a, args)) != null ? _c : args;
621
708
  }
622
709
  async doGenerate(options) {
623
- var _a, _b, _c, _d;
624
- const { args, warnings, betas } = await this.getArgs(options);
710
+ var _a, _b, _c, _d, _e;
711
+ const { args, warnings, betas, jsonResponseTool } = await this.getArgs(options);
625
712
  const {
626
713
  responseHeaders,
627
714
  value: response,
@@ -641,7 +728,9 @@ var AnthropicMessagesLanguageModel = class {
641
728
  for (const part of response.content) {
642
729
  switch (part.type) {
643
730
  case "text": {
644
- content.push({ type: "text", text: part.text });
731
+ if (jsonResponseTool == null) {
732
+ content.push({ type: "text", text: part.text });
733
+ }
645
734
  break;
646
735
  }
647
736
  case "thinking": {
@@ -669,43 +758,84 @@ var AnthropicMessagesLanguageModel = class {
669
758
  break;
670
759
  }
671
760
  case "tool_use": {
672
- content.push({
673
- type: "tool-call",
674
- toolCallType: "function",
675
- toolCallId: part.id,
676
- toolName: part.name,
677
- args: JSON.stringify(part.input)
678
- });
761
+ content.push(
762
+ // when a json response tool is used, the tool call becomes the text:
763
+ jsonResponseTool != null ? {
764
+ type: "text",
765
+ text: JSON.stringify(part.input)
766
+ } : {
767
+ type: "tool-call",
768
+ toolCallType: "function",
769
+ toolCallId: part.id,
770
+ toolName: part.name,
771
+ args: JSON.stringify(part.input)
772
+ }
773
+ );
774
+ break;
775
+ }
776
+ case "server_tool_use": {
777
+ continue;
778
+ }
779
+ case "web_search_tool_result": {
780
+ if (Array.isArray(part.content)) {
781
+ for (const result of part.content) {
782
+ if (result.type === "web_search_result") {
783
+ content.push({
784
+ type: "source",
785
+ sourceType: "url",
786
+ id: this.generateId(),
787
+ url: result.url,
788
+ title: result.title,
789
+ providerMetadata: {
790
+ anthropic: {
791
+ encryptedContent: result.encrypted_content,
792
+ pageAge: (_a = result.page_age) != null ? _a : null
793
+ }
794
+ }
795
+ });
796
+ }
797
+ }
798
+ } else if (part.content.type === "web_search_tool_result_error") {
799
+ throw new APICallError({
800
+ message: `Web search failed: ${part.content.error_code}`,
801
+ url: "web_search_api",
802
+ requestBodyValues: { tool_use_id: part.tool_use_id },
803
+ data: { error_code: part.content.error_code }
804
+ });
805
+ }
679
806
  break;
680
807
  }
681
808
  }
682
809
  }
683
810
  return {
684
811
  content,
685
- finishReason: mapAnthropicStopReason(response.stop_reason),
812
+ finishReason: mapAnthropicStopReason({
813
+ finishReason: response.stop_reason,
814
+ isJsonResponseFromTool: jsonResponseTool != null
815
+ }),
686
816
  usage: {
687
817
  inputTokens: response.usage.input_tokens,
688
818
  outputTokens: response.usage.output_tokens,
689
819
  totalTokens: response.usage.input_tokens + response.usage.output_tokens,
690
- cachedInputTokens: (_a = response.usage.cache_read_input_tokens) != null ? _a : void 0
820
+ cachedInputTokens: (_b = response.usage.cache_read_input_tokens) != null ? _b : void 0
691
821
  },
692
822
  request: { body: args },
693
823
  response: {
694
- id: (_b = response.id) != null ? _b : void 0,
695
- modelId: (_c = response.model) != null ? _c : void 0,
824
+ id: (_c = response.id) != null ? _c : void 0,
825
+ modelId: (_d = response.model) != null ? _d : void 0,
696
826
  headers: responseHeaders,
697
827
  body: rawResponse
698
828
  },
699
829
  warnings,
700
830
  providerMetadata: {
701
831
  anthropic: {
702
- cacheCreationInputTokens: (_d = response.usage.cache_creation_input_tokens) != null ? _d : null
832
+ cacheCreationInputTokens: (_e = response.usage.cache_creation_input_tokens) != null ? _e : null
703
833
  }
704
834
  }
705
835
  };
706
836
  }
707
837
  async doStream(options) {
708
- const { args, warnings, betas } = await this.getArgs(options);
838
+ const { args, warnings, betas, jsonResponseTool } = await this.getArgs(options);
709
839
  const body = { ...args, stream: true };
710
840
  const { responseHeaders, value: response } = await postJsonToApi({
711
841
  url: this.buildRequestUrl(true),
@@ -727,6 +857,8 @@ var AnthropicMessagesLanguageModel = class {
727
857
  const toolCallContentBlocks = {};
728
858
  let providerMetadata = void 0;
729
859
  let blockType = void 0;
860
+ const config = this.config;
861
+ const generateId2 = this.generateId;
730
862
  return {
731
863
  stream: response.pipeThrough(
732
864
  new TransformStream({
@@ -734,7 +866,7 @@ var AnthropicMessagesLanguageModel = class {
734
866
  controller.enqueue({ type: "stream-start", warnings });
735
867
  },
736
868
  transform(chunk, controller) {
737
- var _a, _b, _c, _d, _e, _f;
869
+ var _a, _b, _c, _d, _e, _f, _g;
738
870
  if (!chunk.success) {
739
871
  controller.enqueue({ type: "error", error: chunk.error });
740
872
  return;
@@ -773,6 +905,40 @@ var AnthropicMessagesLanguageModel = class {
773
905
  };
774
906
  return;
775
907
  }
908
+ case "server_tool_use": {
909
+ return;
910
+ }
911
+ case "web_search_tool_result": {
912
+ if (Array.isArray(value.content_block.content)) {
913
+ for (const result of value.content_block.content) {
914
+ if (result.type === "web_search_result") {
915
+ controller.enqueue({
916
+ type: "source",
917
+ sourceType: "url",
918
+ id: generateId2(),
919
+ url: result.url,
920
+ title: result.title,
921
+ providerMetadata: {
922
+ anthropic: {
923
+ encryptedContent: result.encrypted_content,
924
+ pageAge: (_a = result.page_age) != null ? _a : null
925
+ }
926
+ }
927
+ });
928
+ }
929
+ }
930
+ } else if (value.content_block.content.type === "web_search_tool_result_error") {
931
+ controller.enqueue({
932
+ type: "error",
933
+ error: {
934
+ type: "web-search-error",
935
+ message: `Web search failed: ${value.content_block.content.error_code}`,
936
+ code: value.content_block.content.error_code
937
+ }
938
+ });
939
+ }
940
+ return;
941
+ }
776
942
  default: {
777
943
  const _exhaustiveCheck = contentBlockType;
778
944
  throw new Error(
@@ -784,13 +950,15 @@ var AnthropicMessagesLanguageModel = class {
784
950
  case "content_block_stop": {
785
951
  if (toolCallContentBlocks[value.index] != null) {
786
952
  const contentBlock = toolCallContentBlocks[value.index];
787
- controller.enqueue({
788
- type: "tool-call",
789
- toolCallType: "function",
790
- toolCallId: contentBlock.toolCallId,
791
- toolName: contentBlock.toolName,
792
- args: contentBlock.jsonText
793
- });
953
+ if (jsonResponseTool == null) {
954
+ controller.enqueue({
955
+ type: "tool-call",
956
+ toolCallType: "function",
957
+ toolCallId: contentBlock.toolCallId,
958
+ toolName: contentBlock.toolName,
959
+ args: contentBlock.jsonText
960
+ });
961
+ }
794
962
  delete toolCallContentBlocks[value.index];
795
963
  }
796
964
  blockType = void 0;
@@ -800,6 +968,9 @@ var AnthropicMessagesLanguageModel = class {
800
968
  const deltaType = value.delta.type;
801
969
  switch (deltaType) {
802
970
  case "text_delta": {
971
+ if (jsonResponseTool != null) {
972
+ return;
973
+ }
803
974
  controller.enqueue({
804
975
  type: "text",
805
976
  text: value.delta.text
@@ -830,16 +1001,27 @@ var AnthropicMessagesLanguageModel = class {
830
1001
  }
831
1002
  case "input_json_delta": {
832
1003
  const contentBlock = toolCallContentBlocks[value.index];
833
- controller.enqueue({
834
- type: "tool-call-delta",
835
- toolCallType: "function",
836
- toolCallId: contentBlock.toolCallId,
837
- toolName: contentBlock.toolName,
838
- argsTextDelta: value.delta.partial_json
839
- });
1004
+ if (!contentBlock) {
1005
+ return;
1006
+ }
1007
+ controller.enqueue(
1008
+ jsonResponseTool != null ? {
1009
+ type: "text",
1010
+ text: value.delta.partial_json
1011
+ } : {
1012
+ type: "tool-call-delta",
1013
+ toolCallType: "function",
1014
+ toolCallId: contentBlock.toolCallId,
1015
+ toolName: contentBlock.toolName,
1016
+ argsTextDelta: value.delta.partial_json
1017
+ }
1018
+ );
840
1019
  contentBlock.jsonText += value.delta.partial_json;
841
1020
  return;
842
1021
  }
1022
+ case "citations_delta": {
1023
+ return;
1024
+ }
843
1025
  default: {
844
1026
  const _exhaustiveCheck = deltaType;
845
1027
  throw new Error(
@@ -850,23 +1032,26 @@ var AnthropicMessagesLanguageModel = class {
850
1032
  }
851
1033
  case "message_start": {
852
1034
  usage.inputTokens = value.message.usage.input_tokens;
853
- usage.cachedInputTokens = (_a = value.message.usage.cache_read_input_tokens) != null ? _a : void 0;
1035
+ usage.cachedInputTokens = (_b = value.message.usage.cache_read_input_tokens) != null ? _b : void 0;
854
1036
  providerMetadata = {
855
1037
  anthropic: {
856
- cacheCreationInputTokens: (_b = value.message.usage.cache_creation_input_tokens) != null ? _b : null
1038
+ cacheCreationInputTokens: (_c = value.message.usage.cache_creation_input_tokens) != null ? _c : null
857
1039
  }
858
1040
  };
859
1041
  controller.enqueue({
860
1042
  type: "response-metadata",
861
- id: (_c = value.message.id) != null ? _c : void 0,
862
- modelId: (_d = value.message.model) != null ? _d : void 0
1043
+ id: (_d = value.message.id) != null ? _d : void 0,
1044
+ modelId: (_e = value.message.model) != null ? _e : void 0
863
1045
  });
864
1046
  return;
865
1047
  }
866
1048
  case "message_delta": {
867
1049
  usage.outputTokens = value.usage.output_tokens;
868
- usage.totalTokens = ((_e = usage.inputTokens) != null ? _e : 0) + ((_f = value.usage.output_tokens) != null ? _f : 0);
869
- finishReason = mapAnthropicStopReason(value.delta.stop_reason);
1050
+ usage.totalTokens = ((_f = usage.inputTokens) != null ? _f : 0) + ((_g = value.usage.output_tokens) != null ? _g : 0);
1051
+ finishReason = mapAnthropicStopReason({
1052
+ finishReason: value.delta.stop_reason,
1053
+ isJsonResponseFromTool: jsonResponseTool != null
1054
+ });
870
1055
  return;
871
1056
  }
872
1057
  case "message_stop": {
@@ -919,6 +1104,31 @@ var anthropicMessagesResponseSchema = z3.object({
919
1104
  id: z3.string(),
920
1105
  name: z3.string(),
921
1106
  input: z3.unknown()
1107
+ }),
1108
+ z3.object({
1109
+ type: z3.literal("server_tool_use"),
1110
+ id: z3.string(),
1111
+ name: z3.string(),
1112
+ input: z3.record(z3.unknown()).nullish()
1113
+ }),
1114
+ z3.object({
1115
+ type: z3.literal("web_search_tool_result"),
1116
+ tool_use_id: z3.string(),
1117
+ content: z3.union([
1118
+ z3.array(
1119
+ z3.object({
1120
+ type: z3.literal("web_search_result"),
1121
+ url: z3.string(),
1122
+ title: z3.string(),
1123
+ encrypted_content: z3.string(),
1124
+ page_age: z3.string().nullish()
1125
+ })
1126
+ ),
1127
+ z3.object({
1128
+ type: z3.literal("web_search_tool_result_error"),
1129
+ error_code: z3.string()
1130
+ })
1131
+ ])
922
1132
  })
923
1133
  ])
924
1134
  ),
@@ -927,7 +1137,10 @@ var anthropicMessagesResponseSchema = z3.object({
927
1137
  input_tokens: z3.number(),
928
1138
  output_tokens: z3.number(),
929
1139
  cache_creation_input_tokens: z3.number().nullish(),
930
- cache_read_input_tokens: z3.number().nullish()
1140
+ cache_read_input_tokens: z3.number().nullish(),
1141
+ server_tool_use: z3.object({
1142
+ web_search_requests: z3.number()
1143
+ }).nullish()
931
1144
  })
932
1145
  });
933
1146
  var anthropicMessagesChunkSchema = z3.discriminatedUnion("type", [
@@ -964,6 +1177,31 @@ var anthropicMessagesChunkSchema = z3.discriminatedUnion("type", [
964
1177
  z3.object({
965
1178
  type: z3.literal("redacted_thinking"),
966
1179
  data: z3.string()
1180
+ }),
1181
+ z3.object({
1182
+ type: z3.literal("server_tool_use"),
1183
+ id: z3.string(),
1184
+ name: z3.string(),
1185
+ input: z3.record(z3.unknown()).nullish()
1186
+ }),
1187
+ z3.object({
1188
+ type: z3.literal("web_search_tool_result"),
1189
+ tool_use_id: z3.string(),
1190
+ content: z3.union([
1191
+ z3.array(
1192
+ z3.object({
1193
+ type: z3.literal("web_search_result"),
1194
+ url: z3.string(),
1195
+ title: z3.string(),
1196
+ encrypted_content: z3.string(),
1197
+ page_age: z3.string().nullish()
1198
+ })
1199
+ ),
1200
+ z3.object({
1201
+ type: z3.literal("web_search_tool_result_error"),
1202
+ error_code: z3.string()
1203
+ })
1204
+ ])
967
1205
  })
968
1206
  ])
969
1207
  }),
@@ -986,6 +1224,16 @@ var anthropicMessagesChunkSchema = z3.discriminatedUnion("type", [
986
1224
  z3.object({
987
1225
  type: z3.literal("signature_delta"),
988
1226
  signature: z3.string()
1227
+ }),
1228
+ z3.object({
1229
+ type: z3.literal("citations_delta"),
1230
+ citation: z3.object({
1231
+ type: z3.literal("web_search_result_location"),
1232
+ cited_text: z3.string(),
1233
+ url: z3.string(),
1234
+ title: z3.string(),
1235
+ encrypted_index: z3.string()
1236
+ })
989
1237
  })
990
1238
  ])
991
1239
  }),