@ai-sdk/amazon-bedrock 3.0.56 → 3.0.59

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @ai-sdk/amazon-bedrock
2
2
 
3
+ ## 3.0.59
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [3a7a427]
8
+ - @ai-sdk/anthropic@2.0.47
9
+
10
+ ## 3.0.58
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [54a0480]
15
+ - @ai-sdk/anthropic@2.0.46
16
+
17
+ ## 3.0.57
18
+
19
+ ### Patch Changes
20
+
21
+ - 708df55: feat(provider/amazon-bedrock,provider/google-vertex-anthropic): add support for tool calling with structured output
22
+
23
+ Added support for combining tool calling with structured outputs in both Amazon Bedrock and Google Vertex Anthropic providers. This allows developers to use tools (like weather lookups, web search, etc.) alongside structured JSON output schemas, enabling multi-step agentic workflows with structured final outputs.
24
+
25
+ **Amazon Bedrock Changes:**
26
+
27
+ - Removed incorrect warning that prevented using tools with JSON response format
28
+ - Updated tool choice to use `{ type: 'required' }` instead of specific tool selection when using structured outputs
29
+ - Added `isJsonResponseFromTool` parameter to finish reason mapping
30
+ - JSON tool responses are correctly converted to text content and finish reason is mapped from `tool_use` to `stop`
31
+ - Added comprehensive test coverage for combining tools with structured outputs
32
+ - Added example files demonstrating the feature
33
+
34
+ **Google Vertex Anthropic Changes:**
35
+
36
+ - Inherits support from underlying Anthropic provider implementation
37
+ - Added test coverage to verify the feature works correctly
38
+ - Added example files demonstrating the feature
39
+
40
+ This brings Anthropic provider's structured output capabilities to the Amazon Bedrock and Google Vertex Anthropic providers.
41
+
3
42
  ## 3.0.56
4
43
 
5
44
  ### Patch Changes
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ module.exports = __toCommonJS(src_exports);
30
30
  var import_provider_utils8 = require("@ai-sdk/provider-utils");
31
31
 
32
32
  // src/version.ts
33
- var VERSION = true ? "3.0.56" : "0.0.0-test";
33
+ var VERSION = true ? "3.0.59" : "0.0.0-test";
34
34
 
35
35
  // src/bedrock-provider.ts
36
36
  var import_internal2 = require("@ai-sdk/anthropic/internal");
@@ -649,7 +649,7 @@ function groupIntoBlocks(prompt) {
649
649
  }
650
650
 
651
651
  // src/map-bedrock-finish-reason.ts
652
- function mapBedrockFinishReason(finishReason) {
652
+ function mapBedrockFinishReason(finishReason, isJsonResponseFromTool) {
653
653
  switch (finishReason) {
654
654
  case "stop_sequence":
655
655
  case "end_turn":
@@ -660,7 +660,7 @@ function mapBedrockFinishReason(finishReason) {
660
660
  case "guardrail_intervened":
661
661
  return "content-filter";
662
662
  case "tool_use":
663
- return "tool-calls";
663
+ return isJsonResponseFromTool ? "stop" : "tool-calls";
664
664
  default:
665
665
  return "unknown";
666
666
  }
@@ -739,14 +739,6 @@ var BedrockChatLanguageModel = class {
739
739
  details: "Only text and json response formats are supported."
740
740
  });
741
741
  }
742
- if (tools != null && (responseFormat == null ? void 0 : responseFormat.type) === "json") {
743
- if (tools.length > 0) {
744
- warnings.push({
745
- type: "other",
746
- message: "JSON response format does not support tools. The provided tools are ignored."
747
- });
748
- }
749
- }
750
742
  const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null ? {
751
743
  type: "function",
752
744
  name: "json",
@@ -754,8 +746,8 @@ var BedrockChatLanguageModel = class {
754
746
  inputSchema: responseFormat.schema
755
747
  } : void 0;
756
748
  const { toolConfig, additionalTools, toolWarnings, betas } = await prepareTools({
757
- tools: jsonResponseTool ? [jsonResponseTool, ...tools != null ? tools : []] : tools,
758
- toolChoice: jsonResponseTool != null ? { type: "tool", toolName: jsonResponseTool.name } : toolChoice,
749
+ tools: jsonResponseTool ? [...tools != null ? tools : [], jsonResponseTool] : tools,
750
+ toolChoice: jsonResponseTool != null ? { type: "required" } : toolChoice,
759
751
  modelId: this.modelId
760
752
  });
761
753
  warnings.push(...toolWarnings);
@@ -899,11 +891,10 @@ var BedrockChatLanguageModel = class {
899
891
  fetch: this.config.fetch
900
892
  });
901
893
  const content = [];
894
+ let isJsonResponseFromTool = false;
902
895
  for (const part of response.output.message.content) {
903
896
  if (part.text) {
904
- if (!usesJsonResponseTool) {
905
- content.push({ type: "text", text: part.text });
906
- }
897
+ content.push({ type: "text", text: part.text });
907
898
  }
908
899
  if (part.reasoningContent) {
909
900
  if ("reasoningText" in part.reasoningContent) {
@@ -932,21 +923,24 @@ var BedrockChatLanguageModel = class {
932
923
  }
933
924
  }
934
925
  if (part.toolUse) {
935
- content.push(
936
- // when a json response tool is used, the tool call becomes the text:
937
- usesJsonResponseTool ? {
926
+ const isJsonResponseTool = usesJsonResponseTool && part.toolUse.name === "json";
927
+ if (isJsonResponseTool) {
928
+ isJsonResponseFromTool = true;
929
+ content.push({
938
930
  type: "text",
939
931
  text: JSON.stringify(part.toolUse.input)
940
- } : {
932
+ });
933
+ } else {
934
+ content.push({
941
935
  type: "tool-call",
942
936
  toolCallId: (_c = (_b = part.toolUse) == null ? void 0 : _b.toolUseId) != null ? _c : this.config.generateId(),
943
937
  toolName: (_e = (_d = part.toolUse) == null ? void 0 : _d.name) != null ? _e : `tool-${this.config.generateId()}`,
944
938
  input: JSON.stringify((_g = (_f = part.toolUse) == null ? void 0 : _f.input) != null ? _g : "")
945
- }
946
- );
939
+ });
940
+ }
947
941
  }
948
942
  }
949
- const providerMetadata = response.trace || response.usage || usesJsonResponseTool ? {
943
+ const providerMetadata = response.trace || response.usage || isJsonResponseFromTool ? {
950
944
  bedrock: {
951
945
  ...response.trace && typeof response.trace === "object" ? { trace: response.trace } : {},
952
946
  ...((_h = response.usage) == null ? void 0 : _h.cacheWriteInputTokens) != null && {
@@ -954,13 +948,14 @@ var BedrockChatLanguageModel = class {
954
948
  cacheWriteInputTokens: response.usage.cacheWriteInputTokens
955
949
  }
956
950
  },
957
- ...usesJsonResponseTool && { isJsonResponseFromTool: true }
951
+ ...isJsonResponseFromTool && { isJsonResponseFromTool: true }
958
952
  }
959
953
  } : void 0;
960
954
  return {
961
955
  content,
962
956
  finishReason: mapBedrockFinishReason(
963
- response.stopReason
957
+ response.stopReason,
958
+ isJsonResponseFromTool
964
959
  ),
965
960
  usage: {
966
961
  inputTokens: (_i = response.usage) == null ? void 0 : _i.inputTokens,
@@ -1002,6 +997,7 @@ var BedrockChatLanguageModel = class {
1002
997
  totalTokens: void 0
1003
998
  };
1004
999
  let providerMetadata = void 0;
1000
+ let isJsonResponseFromTool = false;
1005
1001
  const contentBlocks = {};
1006
1002
  return {
1007
1003
  stream: response.pipeThrough(
@@ -1041,7 +1037,8 @@ var BedrockChatLanguageModel = class {
1041
1037
  }
1042
1038
  if (value.messageStop) {
1043
1039
  finishReason = mapBedrockFinishReason(
1044
- value.messageStop.stopReason
1040
+ value.messageStop.stopReason,
1041
+ isJsonResponseFromTool
1045
1042
  );
1046
1043
  }
1047
1044
  if (value.metadata) {
@@ -1057,14 +1054,11 @@ var BedrockChatLanguageModel = class {
1057
1054
  const trace = value.metadata.trace ? {
1058
1055
  trace: value.metadata.trace
1059
1056
  } : void 0;
1060
- if (cacheUsage || trace || usesJsonResponseTool) {
1057
+ if (cacheUsage || trace) {
1061
1058
  providerMetadata = {
1062
1059
  bedrock: {
1063
1060
  ...cacheUsage,
1064
- ...trace,
1065
- ...usesJsonResponseTool && {
1066
- isJsonResponseFromTool: true
1067
- }
1061
+ ...trace
1068
1062
  }
1069
1063
  };
1070
1064
  }
@@ -1081,20 +1075,16 @@ var BedrockChatLanguageModel = class {
1081
1075
  const blockIndex = value.contentBlockDelta.contentBlockIndex || 0;
1082
1076
  if (contentBlocks[blockIndex] == null) {
1083
1077
  contentBlocks[blockIndex] = { type: "text" };
1084
- if (!usesJsonResponseTool) {
1085
- controller.enqueue({
1086
- type: "text-start",
1087
- id: String(blockIndex)
1088
- });
1089
- }
1090
- }
1091
- if (!usesJsonResponseTool) {
1092
1078
  controller.enqueue({
1093
- type: "text-delta",
1094
- id: String(blockIndex),
1095
- delta: value.contentBlockDelta.delta.text
1079
+ type: "text-start",
1080
+ id: String(blockIndex)
1096
1081
  });
1097
1082
  }
1083
+ controller.enqueue({
1084
+ type: "text-delta",
1085
+ id: String(blockIndex),
1086
+ delta: value.contentBlockDelta.delta.text
1087
+ });
1098
1088
  }
1099
1089
  if (((_n = value.contentBlockStop) == null ? void 0 : _n.contentBlockIndex) != null) {
1100
1090
  const blockIndex = value.contentBlockStop.contentBlockIndex;
@@ -1106,14 +1096,13 @@ var BedrockChatLanguageModel = class {
1106
1096
  id: String(blockIndex)
1107
1097
  });
1108
1098
  } else if (contentBlock.type === "text") {
1109
- if (!usesJsonResponseTool) {
1110
- controller.enqueue({
1111
- type: "text-end",
1112
- id: String(blockIndex)
1113
- });
1114
- }
1099
+ controller.enqueue({
1100
+ type: "text-end",
1101
+ id: String(blockIndex)
1102
+ });
1115
1103
  } else if (contentBlock.type === "tool-call") {
1116
- if (usesJsonResponseTool) {
1104
+ if (contentBlock.isJsonResponseTool) {
1105
+ isJsonResponseFromTool = true;
1117
1106
  controller.enqueue({
1118
1107
  type: "text-start",
1119
1108
  id: String(blockIndex)
@@ -1187,13 +1176,15 @@ var BedrockChatLanguageModel = class {
1187
1176
  if (((_p = contentBlockStart == null ? void 0 : contentBlockStart.start) == null ? void 0 : _p.toolUse) != null) {
1188
1177
  const toolUse = contentBlockStart.start.toolUse;
1189
1178
  const blockIndex = contentBlockStart.contentBlockIndex;
1179
+ const isJsonResponseTool = usesJsonResponseTool && toolUse.name === "json";
1190
1180
  contentBlocks[blockIndex] = {
1191
1181
  type: "tool-call",
1192
1182
  toolCallId: toolUse.toolUseId,
1193
1183
  toolName: toolUse.name,
1194
- jsonText: ""
1184
+ jsonText: "",
1185
+ isJsonResponseTool
1195
1186
  };
1196
- if (!usesJsonResponseTool) {
1187
+ if (!isJsonResponseTool) {
1197
1188
  controller.enqueue({
1198
1189
  type: "tool-input-start",
1199
1190
  id: toolUse.toolUseId,
@@ -1207,7 +1198,7 @@ var BedrockChatLanguageModel = class {
1207
1198
  const contentBlock = contentBlocks[blockIndex];
1208
1199
  if ((contentBlock == null ? void 0 : contentBlock.type) === "tool-call") {
1209
1200
  const delta = (_q = contentBlockDelta.delta.toolUse.input) != null ? _q : "";
1210
- if (!usesJsonResponseTool) {
1201
+ if (!contentBlock.isJsonResponseTool) {
1211
1202
  controller.enqueue({
1212
1203
  type: "tool-input-delta",
1213
1204
  id: contentBlock.toolCallId,
@@ -1219,6 +1210,20 @@ var BedrockChatLanguageModel = class {
1219
1210
  }
1220
1211
  },
1221
1212
  flush(controller) {
1213
+ if (isJsonResponseFromTool) {
1214
+ if (providerMetadata) {
1215
+ providerMetadata.bedrock = {
1216
+ ...providerMetadata.bedrock,
1217
+ isJsonResponseFromTool: true
1218
+ };
1219
+ } else {
1220
+ providerMetadata = {
1221
+ bedrock: {
1222
+ isJsonResponseFromTool: true
1223
+ }
1224
+ };
1225
+ }
1226
+ }
1222
1227
  controller.enqueue({
1223
1228
  type: "finish",
1224
1229
  finishReason,