@ai-sdk/amazon-bedrock 5.0.20 → 5.0.21

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.
@@ -35,7 +35,7 @@ var import_provider_utils = require("@ai-sdk/provider-utils");
35
35
  var import_aws4fetch = require("aws4fetch");
36
36
 
37
37
  // src/version.ts
38
- var VERSION = true ? "5.0.20" : "0.0.0-test";
38
+ var VERSION = true ? "5.0.21" : "0.0.0-test";
39
39
 
40
40
  // src/amazon-bedrock-sigv4-fetch.ts
41
41
  function createSigV4FetchFunction(getCredentials, fetch, service = "bedrock") {
@@ -23,7 +23,7 @@ import {
23
23
  import { AwsV4Signer } from "aws4fetch";
24
24
 
25
25
  // src/version.ts
26
- var VERSION = true ? "5.0.20" : "0.0.0-test";
26
+ var VERSION = true ? "5.0.21" : "0.0.0-test";
27
27
 
28
28
  // src/amazon-bedrock-sigv4-fetch.ts
29
29
  function createSigV4FetchFunction(getCredentials, fetch, service = "bedrock") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/amazon-bedrock",
3
- "version": "5.0.20",
3
+ "version": "5.0.21",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -44,10 +44,10 @@
44
44
  "@smithy/eventstream-codec": "^4.3.3",
45
45
  "@smithy/util-utf8": "^4.3.3",
46
46
  "aws4fetch": "^1.0.20",
47
- "@ai-sdk/anthropic": "4.0.14",
48
- "@ai-sdk/openai": "4.0.13",
47
+ "@ai-sdk/anthropic": "4.0.15",
48
+ "@ai-sdk/openai": "4.0.14",
49
49
  "@ai-sdk/provider": "4.0.3",
50
- "@ai-sdk/provider-utils": "5.0.9"
50
+ "@ai-sdk/provider-utils": "5.0.10"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "22.19.19",
@@ -16,6 +16,7 @@ import {
16
16
  combineHeaders,
17
17
  createJsonErrorResponseHandler,
18
18
  createJsonResponseHandler,
19
+ injectJsonInstructionIntoMessages,
19
20
  isCustomReasoning,
20
21
  mapReasoningToProviderBudget,
21
22
  mapReasoningToProviderEffort,
@@ -101,6 +102,7 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
101
102
  }: LanguageModelV4CallOptions): Promise<{
102
103
  command: AmazonBedrockConverseInput;
103
104
  warnings: SharedV4Warning[];
105
+ usesJsonInstruction: boolean;
104
106
  usesJsonResponseTool: boolean;
105
107
  betas: Set<string>;
106
108
  }> {
@@ -188,16 +190,33 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
188
190
  const { supportsStructuredOutput: modelSupportsStructuredOutput } =
189
191
  getModelCapabilities(this.modelId);
190
192
 
193
+ const modelRejectsNativeStructuredOutput =
194
+ this.modelId.includes('claude-opus-4-7') ||
195
+ this.modelId.includes('claude-opus-4-8') ||
196
+ this.modelId.includes('claude-fable-5') ||
197
+ this.modelId.includes('claude-sonnet-5');
198
+
191
199
  const useNativeStructuredOutput =
192
200
  isAnthropicModel &&
201
+ !modelRejectsNativeStructuredOutput &&
193
202
  (modelSupportsStructuredOutput || isThinkingEnabled) &&
194
203
  responseFormat?.type === 'json' &&
195
204
  responseFormat.schema != null;
196
205
 
206
+ const useJsonInstructionForStructuredOutput =
207
+ isAnthropicModel &&
208
+ (this.modelId.includes('claude-opus-4-7') ||
209
+ this.modelId.includes('claude-opus-4-8')) &&
210
+ responseFormat?.type === 'json' &&
211
+ responseFormat.schema != null &&
212
+ tools != null &&
213
+ tools.length > 0;
214
+
197
215
  const jsonResponseTool: LanguageModelV4FunctionTool | undefined =
198
216
  responseFormat?.type === 'json' &&
199
217
  responseFormat.schema != null &&
200
- !useNativeStructuredOutput
218
+ !useNativeStructuredOutput &&
219
+ !useJsonInstructionForStructuredOutput
201
220
  ? {
202
221
  type: 'function',
203
222
  name: 'json',
@@ -409,6 +428,15 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
409
428
  }
410
429
  }
411
430
 
431
+ if (useJsonInstructionForStructuredOutput) {
432
+ filteredPrompt = injectJsonInstructionIntoMessages({
433
+ messages: filteredPrompt,
434
+ schema: responseFormat!.schema,
435
+ schemaSuffix:
436
+ 'You MUST answer with only a JSON object that matches the JSON schema above. Do not wrap it in markdown fences or include any other text.',
437
+ });
438
+ }
439
+
412
440
  const isMistral = isMistralModel(this.modelId);
413
441
  const { system, messages } = await convertToAmazonBedrockChatMessages(
414
442
  filteredPrompt,
@@ -450,6 +478,7 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
450
478
  : {}),
451
479
  },
452
480
  warnings,
481
+ usesJsonInstruction: useJsonInstructionForStructuredOutput,
453
482
  usesJsonResponseTool: jsonResponseTool != null,
454
483
  betas,
455
484
  };
@@ -476,6 +505,7 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
476
505
  const {
477
506
  command: args,
478
507
  warnings,
508
+ usesJsonInstruction,
479
509
  usesJsonResponseTool,
480
510
  } = await this.getArgs(options);
481
511
 
@@ -497,12 +527,18 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
497
527
 
498
528
  const content: Array<LanguageModelV4Content> = [];
499
529
  let isJsonResponseFromTool = false;
530
+ const jsonObjectTextExtractor = usesJsonInstruction
531
+ ? new JsonObjectTextExtractor()
532
+ : undefined;
500
533
 
501
534
  // map response content to content array
502
535
  for (const part of response.output.message.content) {
503
536
  // text
504
537
  if (part.text != null) {
505
- content.push({ type: 'text', text: part.text });
538
+ content.push({
539
+ type: 'text',
540
+ text: jsonObjectTextExtractor?.process(part.text) ?? part.text,
541
+ });
506
542
  }
507
543
 
508
544
  // reasoning
@@ -639,6 +675,7 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
639
675
  const {
640
676
  command: args,
641
677
  warnings,
678
+ usesJsonInstruction,
642
679
  usesJsonResponseTool,
643
680
  } = await this.getArgs(options);
644
681
  const modelId = this.modelId;
@@ -668,6 +705,9 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
668
705
  let providerMetadata: SharedV4ProviderMetadata | undefined = undefined;
669
706
  let isJsonResponseFromTool = false;
670
707
  let stopSequence: string | null = null;
708
+ const jsonObjectTextExtractor = usesJsonInstruction
709
+ ? new JsonObjectTextExtractor()
710
+ : undefined;
671
711
 
672
712
  const contentBlocks: Record<
673
713
  number,
@@ -829,11 +869,18 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
829
869
  });
830
870
  }
831
871
 
832
- controller.enqueue({
833
- type: 'text-delta',
834
- id: String(blockIndex),
835
- delta: value.contentBlockDelta.delta.text,
836
- });
872
+ const textDelta =
873
+ jsonObjectTextExtractor?.process(
874
+ value.contentBlockDelta.delta.text,
875
+ ) ?? value.contentBlockDelta.delta.text;
876
+
877
+ if (textDelta.length > 0) {
878
+ controller.enqueue({
879
+ type: 'text-delta',
880
+ id: String(blockIndex),
881
+ delta: textDelta,
882
+ });
883
+ }
837
884
  }
838
885
 
839
886
  if (value.contentBlockStop?.contentBlockIndex != null) {
@@ -1054,6 +1101,68 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
1054
1101
  }
1055
1102
  }
1056
1103
 
1104
+ class JsonObjectTextExtractor {
1105
+ private started = false;
1106
+ private completed = false;
1107
+ private depth = 0;
1108
+ private inString = false;
1109
+ private escaped = false;
1110
+
1111
+ process(text: string): string {
1112
+ let result = '';
1113
+
1114
+ for (const character of text) {
1115
+ if (this.completed) {
1116
+ break;
1117
+ }
1118
+
1119
+ if (!this.started) {
1120
+ if (character !== '{') {
1121
+ continue;
1122
+ }
1123
+
1124
+ this.started = true;
1125
+ this.depth = 1;
1126
+ result += character;
1127
+ continue;
1128
+ }
1129
+
1130
+ result += character;
1131
+
1132
+ if (this.escaped) {
1133
+ this.escaped = false;
1134
+ continue;
1135
+ }
1136
+
1137
+ if (character === '\\' && this.inString) {
1138
+ this.escaped = true;
1139
+ continue;
1140
+ }
1141
+
1142
+ if (character === '"') {
1143
+ this.inString = !this.inString;
1144
+ continue;
1145
+ }
1146
+
1147
+ if (this.inString) {
1148
+ continue;
1149
+ }
1150
+
1151
+ if (character === '{') {
1152
+ this.depth++;
1153
+ } else if (character === '}') {
1154
+ this.depth--;
1155
+
1156
+ if (this.depth === 0) {
1157
+ this.completed = true;
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ return result;
1163
+ }
1164
+ }
1165
+
1057
1166
  const AmazonBedrockStopReasonSchema = z.union([
1058
1167
  z.enum(BEDROCK_STOP_REASONS),
1059
1168
  z.string(),