@ai-sdk/amazon-bedrock 5.0.125 → 5.0.126

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.
@@ -4,7 +4,7 @@ let _ai_sdk_provider = require("@ai-sdk/provider");
4
4
  let _ai_sdk_provider_utils = require("@ai-sdk/provider-utils");
5
5
  let aws4fetch = require("aws4fetch");
6
6
  //#region src/version.ts
7
- const VERSION = "5.0.125";
7
+ const VERSION = "5.0.126";
8
8
  //#endregion
9
9
  //#region src/amazon-bedrock-sigv4-fetch.ts
10
10
  /**
@@ -3,7 +3,7 @@ import { InvalidArgumentError, NoSuchModelError } from "@ai-sdk/provider";
3
3
  import { combineHeaders, getRuntimeEnvironmentUserAgent, isValidHostnamePart, loadOptionalSetting, loadSetting, normalizeHeaders, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
4
4
  import { AwsV4Signer } from "aws4fetch";
5
5
  //#region src/version.ts
6
- const VERSION = "5.0.125";
6
+ const VERSION = "5.0.126";
7
7
  //#endregion
8
8
  //#region src/amazon-bedrock-sigv4-fetch.ts
9
9
  /**
@@ -695,12 +695,24 @@ display-only, and empty configurations also retain portable reasoning.
695
695
 
696
696
  Effort-based Anthropic models can combine portable effort with an explicit
697
697
  thinking configuration. A disabled type prevents effort/budget derivation;
698
- portable `reasoning: 'none'` disables thinking on Anthropic models even when an
699
- enabled type or budget is supplied. Omitting portable reasoning or using
700
- `'provider-default'` leaves the provider configuration unchanged. The legacy
698
+ portable `reasoning: 'none'` requests disabled thinking on Anthropic models even
699
+ when an enabled type or budget is supplied. Omitting portable reasoning or using
700
+ `'provider-default'` uses the provider configuration. The legacy
701
701
  `bedrock` provider options key follows the same rules. See the
702
702
  [reasoning guide](/docs/ai-sdk-core/reasoning#precedence-rules) for precedence details.
703
703
 
704
+ Both `reasoning: 'none'` and `reasoningConfig: { type: 'disabled' }` explicitly
705
+ send `thinking: { type: 'disabled' }` for Anthropic models that support it.
706
+ For Claude 3.5 and earlier, the provider omits `thinking` because these models
707
+ do not support the field.
708
+ Models that require thinking use `between_tools` when supported, or adaptive
709
+ thinking otherwise. For the adaptive fallback, portable `reasoning: 'none'`
710
+ uses explicit `maxReasoningEffort`, then raw `output_config.effort`, and defaults
711
+ to low effort when neither is supplied. Unsupported disabled settings produce warnings.
712
+ If a model rejects disabled or `between_tools`
713
+ thinking at `xhigh` or `max` effort, the provider lowers the effort to `high`
714
+ with a warning.
715
+
704
716
  ```ts
705
717
  import {
706
718
  amazonBedrock,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/amazon-bedrock",
3
- "version": "5.0.125",
3
+ "version": "5.0.126",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -41,10 +41,10 @@
41
41
  }
42
42
  },
43
43
  "dependencies": {
44
- "@ai-sdk/anthropic": "4.0.89",
45
- "@ai-sdk/openai": "4.0.103",
44
+ "@ai-sdk/anthropic": "4.0.90",
45
+ "@ai-sdk/openai": "4.0.104",
46
46
  "@ai-sdk/provider": "4.0.34",
47
- "@ai-sdk/provider-utils": "5.0.69",
47
+ "@ai-sdk/provider-utils": "5.0.70",
48
48
  "@smithy/eventstream-codec": "^4.3.3",
49
49
  "@smithy/util-utf8": "^4.3.3",
50
50
  "aws4fetch": "^1.0.20"
@@ -186,6 +186,9 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
186
186
  supportsStructuredOutput: modelSupportsStructuredOutput,
187
187
  rejectsSamplingParameters,
188
188
  rejectsForcedToolUse,
189
+ rejectsThinkingDisabled,
190
+ rejectsThinkingDisabledAboveHighEffort,
191
+ supportsBetweenToolsThinking,
189
192
  isKnownModel,
190
193
  } = getModelCapabilities(this.modelId);
191
194
 
@@ -284,6 +287,11 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
284
287
  reasoningBudgetTokens: amazonBedrockOptions.reasoningConfig?.budgetTokens,
285
288
  });
286
289
 
290
+ const hasExplicitDisabledThinking =
291
+ amazonBedrockOptions.reasoningConfig?.type === 'disabled';
292
+ const explicitReasoningEffort =
293
+ amazonBedrockOptions.reasoningConfig?.maxReasoningEffort;
294
+
287
295
  amazonBedrockOptions = resolveAmazonBedrockReasoningConfig({
288
296
  reasoning,
289
297
  amazonBedrockOptions,
@@ -293,9 +301,82 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
293
301
  modelId: this.modelId,
294
302
  });
295
303
 
304
+ let thinkingType:
305
+ | 'enabled'
306
+ | 'disabled'
307
+ | 'adaptive'
308
+ | 'between_tools'
309
+ | undefined = amazonBedrockOptions.reasoningConfig?.type;
310
+ let maxReasoningEffort =
311
+ amazonBedrockOptions.reasoningConfig?.maxReasoningEffort;
312
+
313
+ if (isAnthropicModel && thinkingType === 'disabled') {
314
+ if (
315
+ /claude-(?:instant|v?2|3-(?:5-)?(?:haiku|sonnet|opus))(?=[-.:]|$)/.test(
316
+ this.modelId,
317
+ )
318
+ ) {
319
+ // Claude 3.5 and earlier do not accept a thinking field, even disabled.
320
+ thinkingType = undefined;
321
+ } else if (rejectsThinkingDisabled) {
322
+ thinkingType = supportsBetweenToolsThinking
323
+ ? 'between_tools'
324
+ : 'adaptive';
325
+
326
+ if (!hasExplicitDisabledThinking && thinkingType === 'adaptive') {
327
+ maxReasoningEffort ??= explicitReasoningEffort;
328
+
329
+ if (
330
+ maxReasoningEffort == null &&
331
+ amazonBedrockOptions.additionalModelRequestFields?.output_config
332
+ ?.effort == null
333
+ ) {
334
+ maxReasoningEffort = 'low';
335
+ }
336
+ }
337
+
338
+ if (hasExplicitDisabledThinking || thinkingType === 'adaptive') {
339
+ warnings.push({
340
+ type: hasExplicitDisabledThinking ? 'unsupported' : 'compatibility',
341
+ feature: hasExplicitDisabledThinking
342
+ ? 'providerOptions.amazonBedrock.reasoningConfig'
343
+ : 'reasoning',
344
+ details:
345
+ `thinking cannot be disabled for ${this.modelId}. ` +
346
+ `Using '${thinkingType}' thinking instead.`,
347
+ });
348
+ }
349
+ }
350
+
351
+ const effort =
352
+ maxReasoningEffort ??
353
+ amazonBedrockOptions.additionalModelRequestFields?.output_config
354
+ ?.effort;
355
+
356
+ if (
357
+ ((thinkingType === 'disabled' &&
358
+ rejectsThinkingDisabledAboveHighEffort) ||
359
+ thinkingType === 'between_tools') &&
360
+ (effort === 'xhigh' || effort === 'max')
361
+ ) {
362
+ warnings.push({
363
+ type: 'unsupported',
364
+ feature:
365
+ maxReasoningEffort != null
366
+ ? 'providerOptions.amazonBedrock.reasoningConfig.maxReasoningEffort'
367
+ : 'providerOptions.amazonBedrock.additionalModelRequestFields.output_config.effort',
368
+ details:
369
+ `effort '${effort}' is not supported by ${this.modelId} with '${thinkingType}' thinking. ` +
370
+ `The effort has been lowered to 'high'.`,
371
+ });
372
+ maxReasoningEffort = 'high';
373
+ }
374
+ }
375
+
296
376
  const isThinkingEnabled =
297
- amazonBedrockOptions.reasoningConfig?.type === 'enabled' ||
298
- amazonBedrockOptions.reasoningConfig?.type === 'adaptive';
377
+ thinkingType === 'enabled' ||
378
+ thinkingType === 'adaptive' ||
379
+ thinkingType === 'between_tools';
299
380
 
300
381
  const structuredOutputMode =
301
382
  amazonBedrockOptions.structuredOutputMode ??
@@ -407,7 +488,6 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
407
488
  };
408
489
  }
409
490
 
410
- const thinkingType = amazonBedrockOptions.reasoningConfig?.type;
411
491
  const thinkingBudget =
412
492
  thinkingType === 'enabled'
413
493
  ? amazonBedrockOptions.reasoningConfig?.budgetTokens
@@ -426,7 +506,7 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
426
506
  ...(stopSequences != null && { stopSequences }),
427
507
  };
428
508
 
429
- if (isAnthropicThinkingEnabled) {
509
+ if (isAnthropicModel) {
430
510
  if (thinkingBudget != null) {
431
511
  if (inferenceConfig.maxTokens != null) {
432
512
  inferenceConfig.maxTokens += thinkingBudget;
@@ -448,8 +528,16 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
448
528
  ...(thinkingDisplay != null && { display: thinkingDisplay }),
449
529
  },
450
530
  };
531
+ } else if (
532
+ thinkingType === 'disabled' ||
533
+ thinkingType === 'between_tools'
534
+ ) {
535
+ amazonBedrockOptions.additionalModelRequestFields = {
536
+ ...amazonBedrockOptions.additionalModelRequestFields,
537
+ thinking: { type: thinkingType },
538
+ };
451
539
  }
452
- } else if (!isAnthropicModel) {
540
+ } else {
453
541
  if (amazonBedrockOptions.reasoningConfig?.budgetTokens != null) {
454
542
  warnings.push({
455
543
  type: 'unsupported',
@@ -468,9 +556,6 @@ export class AmazonBedrockChatLanguageModel implements LanguageModelV4 {
468
556
  }
469
557
  }
470
558
 
471
- const maxReasoningEffort =
472
- amazonBedrockOptions.reasoningConfig?.maxReasoningEffort;
473
-
474
559
  if (maxReasoningEffort != null) {
475
560
  if (isAnthropicModel) {
476
561
  amazonBedrockOptions.additionalModelRequestFields = {
@@ -1685,8 +1770,8 @@ function resolveAmazonBedrockReasoningConfig({
1685
1770
 
1686
1771
  const result = { ...amazonBedrockOptions };
1687
1772
 
1688
- // Preserve disabled thinking without deriving settings or warnings that will
1689
- // not be sent. Clone the configuration before removing effort and budget.
1773
+ // Do not derive effort or budget from portable reasoning when thinking is
1774
+ // explicitly disabled. Clone the configuration before removing those fields.
1690
1775
  if (reasoningConfig?.type === 'disabled') {
1691
1776
  result.reasoningConfig = { ...reasoningConfig };
1692
1777
  delete result.reasoningConfig.maxReasoningEffort;
@@ -173,8 +173,21 @@ export async function convertToAmazonBedrockChatMessages(
173
173
 
174
174
  let documentCounter = 0;
175
175
  const generateDocumentName = () => `document-${++documentCounter}`;
176
- const getDocumentName = (filename: string | undefined) =>
177
- (filename && sanitizeDocumentName(filename)) || generateDocumentName();
176
+ // Bedrock rejects requests that contain duplicate document names:
177
+ const usedDocumentNames = new Set<string>();
178
+ const getDocumentName = (filename: string | undefined) => {
179
+ const baseName =
180
+ (filename && sanitizeDocumentName(filename)) || generateDocumentName();
181
+
182
+ let name = baseName;
183
+ for (let suffix = 2; usedDocumentNames.has(name); suffix++) {
184
+ const suffixText = ` (${suffix})`;
185
+ name = `${baseName.slice(0, 200 - suffixText.length).trim()}${suffixText}`;
186
+ }
187
+
188
+ usedDocumentNames.add(name);
189
+ return name;
190
+ };
178
191
 
179
192
  for (let i = 0; i < blocks.length; i++) {
180
193
  const block = blocks[i];