@ai-sdk/amazon-bedrock 4.0.161 → 4.0.165
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 +33 -0
- package/dist/anthropic/index.js +1 -1
- package/dist/anthropic/index.mjs +1 -1
- package/dist/index.js +111 -55
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +111 -55
- package/dist/index.mjs.map +1 -1
- package/dist/mantle/index.js +1 -1
- package/dist/mantle/index.mjs +1 -1
- package/package.json +4 -4
- package/src/bedrock-chat-language-model.ts +49 -19
- package/src/bedrock-prepare-tools.ts +30 -1
- package/src/convert-bedrock-usage.ts +7 -1
- package/src/convert-to-bedrock-chat-messages.ts +65 -37
package/dist/mantle/index.js
CHANGED
|
@@ -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 ? "4.0.
|
|
38
|
+
var VERSION = true ? "4.0.165" : "0.0.0-test";
|
|
39
39
|
|
|
40
40
|
// src/bedrock-sigv4-fetch.ts
|
|
41
41
|
function createSigV4FetchFunction(getCredentials, fetch, service = "bedrock") {
|
package/dist/mantle/index.mjs
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
import { AwsV4Signer } from "aws4fetch";
|
|
24
24
|
|
|
25
25
|
// src/version.ts
|
|
26
|
-
var VERSION = true ? "4.0.
|
|
26
|
+
var VERSION = true ? "4.0.165" : "0.0.0-test";
|
|
27
27
|
|
|
28
28
|
// src/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": "4.0.
|
|
3
|
+
"version": "4.0.165",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"@smithy/eventstream-codec": "^4.0.1",
|
|
45
45
|
"@smithy/util-utf8": "^4.0.0",
|
|
46
46
|
"aws4fetch": "^1.0.20",
|
|
47
|
-
"@ai-sdk/anthropic": "3.0.
|
|
48
|
-
"@ai-sdk/openai": "3.0.
|
|
47
|
+
"@ai-sdk/anthropic": "3.0.114",
|
|
48
|
+
"@ai-sdk/openai": "3.0.104",
|
|
49
49
|
"@ai-sdk/provider": "3.0.15",
|
|
50
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
50
|
+
"@ai-sdk/provider-utils": "4.0.49"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "20.17.24",
|
|
@@ -61,6 +61,10 @@ type BedrockChatConfig = {
|
|
|
61
61
|
generateId: () => string;
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
+
const anthropicProviderOptions = z.object({
|
|
65
|
+
disableParallelToolUse: z.boolean().optional(),
|
|
66
|
+
});
|
|
67
|
+
|
|
64
68
|
export class BedrockChatLanguageModel implements LanguageModelV3 {
|
|
65
69
|
readonly specificationVersion = 'v3';
|
|
66
70
|
readonly provider = 'amazon-bedrock';
|
|
@@ -99,6 +103,12 @@ export class BedrockChatLanguageModel implements LanguageModelV3 {
|
|
|
99
103
|
schema: amazonBedrockLanguageModelOptions,
|
|
100
104
|
})) ?? {};
|
|
101
105
|
|
|
106
|
+
const anthropicOptions = await parseProviderOptions({
|
|
107
|
+
provider: 'anthropic',
|
|
108
|
+
providerOptions,
|
|
109
|
+
schema: anthropicProviderOptions,
|
|
110
|
+
});
|
|
111
|
+
|
|
102
112
|
const warnings: SharedV3Warning[] = [];
|
|
103
113
|
|
|
104
114
|
if (frequencyPenalty != null) {
|
|
@@ -151,6 +161,10 @@ export class BedrockChatLanguageModel implements LanguageModelV3 {
|
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
const isAnthropicModel = this.modelId.includes('anthropic');
|
|
164
|
+
const openAIModelId = /^(?:[^.]+\.)?(openai\..+)$/.exec(this.modelId)?.[1];
|
|
165
|
+
const isOpenAIModel = openAIModelId != null;
|
|
166
|
+
const isOpenAIGptOssModel =
|
|
167
|
+
openAIModelId?.startsWith('openai.gpt-oss-') ?? false;
|
|
154
168
|
const isThinkingEnabled =
|
|
155
169
|
bedrockOptions.reasoningConfig?.type === 'enabled' ||
|
|
156
170
|
bedrockOptions.reasoningConfig?.type === 'adaptive';
|
|
@@ -192,6 +206,7 @@ export class BedrockChatLanguageModel implements LanguageModelV3 {
|
|
|
192
206
|
toolChoice:
|
|
193
207
|
jsonResponseTool != null ? { type: 'required' } : toolChoice,
|
|
194
208
|
modelId: this.modelId,
|
|
209
|
+
disableParallelToolUse: anthropicOptions?.disableParallelToolUse,
|
|
195
210
|
});
|
|
196
211
|
|
|
197
212
|
warnings.push(...toolWarnings);
|
|
@@ -279,7 +294,6 @@ export class BedrockChatLanguageModel implements LanguageModelV3 {
|
|
|
279
294
|
|
|
280
295
|
const maxReasoningEffort =
|
|
281
296
|
bedrockOptions.reasoningConfig?.maxReasoningEffort;
|
|
282
|
-
const isOpenAIModel = this.modelId.startsWith('openai.');
|
|
283
297
|
|
|
284
298
|
if (maxReasoningEffort != null) {
|
|
285
299
|
if (isAnthropicModel) {
|
|
@@ -291,11 +305,20 @@ export class BedrockChatLanguageModel implements LanguageModelV3 {
|
|
|
291
305
|
},
|
|
292
306
|
};
|
|
293
307
|
} else if (isOpenAIModel) {
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
308
|
+
// gpt-oss models expect `reasoning_effort` as a flat value, while
|
|
309
|
+
// GPT-5.x models expect a nested `reasoning.effort` object.
|
|
310
|
+
bedrockOptions.additionalModelRequestFields = isOpenAIGptOssModel
|
|
311
|
+
? {
|
|
312
|
+
...bedrockOptions.additionalModelRequestFields,
|
|
313
|
+
reasoning_effort: maxReasoningEffort,
|
|
314
|
+
}
|
|
315
|
+
: {
|
|
316
|
+
...bedrockOptions.additionalModelRequestFields,
|
|
317
|
+
reasoning: {
|
|
318
|
+
...bedrockOptions.additionalModelRequestFields?.reasoning,
|
|
319
|
+
effort: maxReasoningEffort,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
299
322
|
} else {
|
|
300
323
|
// other models (such as Nova 2) use reasoningConfig format
|
|
301
324
|
bedrockOptions.additionalModelRequestFields = {
|
|
@@ -1185,6 +1208,13 @@ const BedrockRedactedReasoningSchema = z.object({
|
|
|
1185
1208
|
data: z.string(),
|
|
1186
1209
|
});
|
|
1187
1210
|
|
|
1211
|
+
const AmazonBedrockCacheDetailSchema = z
|
|
1212
|
+
.object({
|
|
1213
|
+
inputTokens: z.number(),
|
|
1214
|
+
ttl: z.string(),
|
|
1215
|
+
})
|
|
1216
|
+
.catchall(z.json());
|
|
1217
|
+
|
|
1188
1218
|
// limited version of the schema, focused on what is needed for the implementation
|
|
1189
1219
|
// this approach limits breakages when the API changes and increases efficiency
|
|
1190
1220
|
const BedrockResponseSchema = z.object({
|
|
@@ -1227,16 +1257,16 @@ const BedrockResponseSchema = z.object({
|
|
|
1227
1257
|
trace: z.unknown().nullish(),
|
|
1228
1258
|
performanceConfig: z.object({ latency: z.string() }).nullish(),
|
|
1229
1259
|
serviceTier: z.object({ type: z.string() }).nullish(),
|
|
1230
|
-
usage: z
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1260
|
+
usage: z
|
|
1261
|
+
.object({
|
|
1262
|
+
inputTokens: z.number(),
|
|
1263
|
+
outputTokens: z.number(),
|
|
1264
|
+
totalTokens: z.number(),
|
|
1265
|
+
cacheReadInputTokens: z.number().nullish(),
|
|
1266
|
+
cacheWriteInputTokens: z.number().nullish(),
|
|
1267
|
+
cacheDetails: z.array(AmazonBedrockCacheDetailSchema).nullish(),
|
|
1268
|
+
})
|
|
1269
|
+
.catchall(z.json()),
|
|
1240
1270
|
});
|
|
1241
1271
|
|
|
1242
1272
|
// limited version of the schema, focussed on what is needed for the implementation
|
|
@@ -1302,12 +1332,12 @@ const BedrockStreamSchema = z.object({
|
|
|
1302
1332
|
.object({
|
|
1303
1333
|
cacheReadInputTokens: z.number().nullish(),
|
|
1304
1334
|
cacheWriteInputTokens: z.number().nullish(),
|
|
1305
|
-
cacheDetails: z
|
|
1306
|
-
.array(z.object({ inputTokens: z.number(), ttl: z.string() }))
|
|
1307
|
-
.nullish(),
|
|
1335
|
+
cacheDetails: z.array(AmazonBedrockCacheDetailSchema).nullish(),
|
|
1308
1336
|
inputTokens: z.number(),
|
|
1309
1337
|
outputTokens: z.number(),
|
|
1338
|
+
totalTokens: z.number().optional(),
|
|
1310
1339
|
})
|
|
1340
|
+
.catchall(z.json())
|
|
1311
1341
|
.nullish(),
|
|
1312
1342
|
})
|
|
1313
1343
|
.nullish(),
|
|
@@ -19,10 +19,12 @@ export async function prepareTools({
|
|
|
19
19
|
tools,
|
|
20
20
|
toolChoice,
|
|
21
21
|
modelId,
|
|
22
|
+
disableParallelToolUse,
|
|
22
23
|
}: {
|
|
23
24
|
tools: LanguageModelV3CallOptions['tools'];
|
|
24
25
|
toolChoice?: LanguageModelV3CallOptions['toolChoice'];
|
|
25
26
|
modelId: string;
|
|
27
|
+
disableParallelToolUse?: boolean;
|
|
26
28
|
}): Promise<{
|
|
27
29
|
toolConfig: BedrockToolConfiguration;
|
|
28
30
|
additionalTools: Record<string, unknown> | undefined;
|
|
@@ -85,6 +87,7 @@ export async function prepareTools({
|
|
|
85
87
|
} = await prepareAnthropicTools({
|
|
86
88
|
tools: ProviderTools,
|
|
87
89
|
toolChoice,
|
|
90
|
+
disableParallelToolUse,
|
|
88
91
|
supportsStructuredOutput: false,
|
|
89
92
|
supportsStrictTools: false,
|
|
90
93
|
});
|
|
@@ -161,9 +164,35 @@ export async function prepareTools({
|
|
|
161
164
|
});
|
|
162
165
|
}
|
|
163
166
|
|
|
167
|
+
if (
|
|
168
|
+
isAnthropicModel &&
|
|
169
|
+
!usingAnthropicTools &&
|
|
170
|
+
disableParallelToolUse &&
|
|
171
|
+
bedrockTools.length > 0 &&
|
|
172
|
+
toolChoice?.type !== 'none'
|
|
173
|
+
) {
|
|
174
|
+
additionalTools = {
|
|
175
|
+
tool_choice:
|
|
176
|
+
toolChoice?.type === 'required'
|
|
177
|
+
? { type: 'any', disable_parallel_tool_use: true }
|
|
178
|
+
: toolChoice?.type === 'tool'
|
|
179
|
+
? {
|
|
180
|
+
type: 'tool',
|
|
181
|
+
name: toolChoice.toolName,
|
|
182
|
+
disable_parallel_tool_use: true,
|
|
183
|
+
}
|
|
184
|
+
: { type: 'auto', disable_parallel_tool_use: true },
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
164
188
|
// Handle toolChoice for standard Bedrock tools, but NOT for Anthropic provider-defined tools
|
|
165
189
|
let bedrockToolChoice: BedrockToolConfiguration['toolChoice'] = undefined;
|
|
166
|
-
if (
|
|
190
|
+
if (
|
|
191
|
+
!usingAnthropicTools &&
|
|
192
|
+
additionalTools?.tool_choice == null &&
|
|
193
|
+
bedrockTools.length > 0 &&
|
|
194
|
+
toolChoice
|
|
195
|
+
) {
|
|
167
196
|
const type = toolChoice.type;
|
|
168
197
|
switch (type) {
|
|
169
198
|
case 'auto':
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import type { LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
1
|
+
import type { JSONValue, LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
export type BedrockUsage = {
|
|
4
|
+
[key: string]: JSONValue | undefined;
|
|
4
5
|
inputTokens: number;
|
|
5
6
|
outputTokens: number;
|
|
6
7
|
totalTokens?: number;
|
|
7
8
|
cacheReadInputTokens?: number | null;
|
|
8
9
|
cacheWriteInputTokens?: number | null;
|
|
10
|
+
cacheDetails?: Array<{
|
|
11
|
+
[key: string]: JSONValue | undefined;
|
|
12
|
+
inputTokens: number;
|
|
13
|
+
ttl: string;
|
|
14
|
+
}> | null;
|
|
9
15
|
};
|
|
10
16
|
|
|
11
17
|
export function convertBedrockUsage(
|
|
@@ -334,7 +334,12 @@ export async function convertToBedrockChatMessages(
|
|
|
334
334
|
pushCachePoint(bedrockContent, providerOptions);
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
-
messages.
|
|
337
|
+
const previousMessage = messages.at(-1);
|
|
338
|
+
if (previousMessage?.role === 'user') {
|
|
339
|
+
previousMessage.content.push(...bedrockContent);
|
|
340
|
+
} else {
|
|
341
|
+
messages.push({ role: 'user', content: bedrockContent });
|
|
342
|
+
}
|
|
338
343
|
|
|
339
344
|
break;
|
|
340
345
|
}
|
|
@@ -347,8 +352,56 @@ export async function convertToBedrockChatMessages(
|
|
|
347
352
|
const message = block.messages[j];
|
|
348
353
|
const isLastMessage = j === block.messages.length - 1;
|
|
349
354
|
const { content } = message;
|
|
350
|
-
const
|
|
351
|
-
|
|
355
|
+
const convertedReasoningContent: Array<
|
|
356
|
+
BedrockAssistantMessage['content'][number] | undefined
|
|
357
|
+
> = await Promise.all(
|
|
358
|
+
content.map(async part => {
|
|
359
|
+
if (part.type !== 'reasoning') {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const metadata = await parseProviderOptions({
|
|
364
|
+
provider: 'bedrock',
|
|
365
|
+
providerOptions: part.providerOptions,
|
|
366
|
+
schema: bedrockReasoningMetadataSchema,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
if (metadata?.signature != null) {
|
|
370
|
+
return {
|
|
371
|
+
reasoningContent: {
|
|
372
|
+
reasoningText: {
|
|
373
|
+
// do not trim reasoning text when a signature is present:
|
|
374
|
+
// the signature validates the exact original bytes
|
|
375
|
+
text: part.text,
|
|
376
|
+
signature: metadata.signature,
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (metadata?.redactedContent != null) {
|
|
383
|
+
return {
|
|
384
|
+
reasoningContent: {
|
|
385
|
+
redactedContent: metadata.redactedContent,
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (metadata?.redactedData != null) {
|
|
391
|
+
return {
|
|
392
|
+
reasoningContent: {
|
|
393
|
+
redactedReasoning: {
|
|
394
|
+
data: metadata.redactedData,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return undefined;
|
|
401
|
+
}),
|
|
402
|
+
);
|
|
403
|
+
const hasReplayableReasoningBlocks = convertedReasoningContent.some(
|
|
404
|
+
part => part != null,
|
|
352
405
|
);
|
|
353
406
|
|
|
354
407
|
for (let k = 0; k < content.length; k++) {
|
|
@@ -357,8 +410,9 @@ export async function convertToBedrockChatMessages(
|
|
|
357
410
|
|
|
358
411
|
switch (part.type) {
|
|
359
412
|
case 'text': {
|
|
360
|
-
// Skip empty text blocks unless reasoning blocks are
|
|
361
|
-
|
|
413
|
+
// Skip empty text blocks unless replayable reasoning blocks are
|
|
414
|
+
// present and the original block order must be preserved.
|
|
415
|
+
if (!part.text.trim() && !hasReplayableReasoningBlocks) {
|
|
362
416
|
break;
|
|
363
417
|
}
|
|
364
418
|
|
|
@@ -378,37 +432,9 @@ export async function convertToBedrockChatMessages(
|
|
|
378
432
|
}
|
|
379
433
|
|
|
380
434
|
case 'reasoning': {
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
schema: bedrockReasoningMetadataSchema,
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
if (reasoningMetadata?.signature != null) {
|
|
388
|
-
// do not trim reasoning text when a signature is present:
|
|
389
|
-
// the signature validates the exact original bytes
|
|
390
|
-
bedrockContent.push({
|
|
391
|
-
reasoningContent: {
|
|
392
|
-
reasoningText: {
|
|
393
|
-
text: part.text,
|
|
394
|
-
signature: reasoningMetadata.signature,
|
|
395
|
-
},
|
|
396
|
-
},
|
|
397
|
-
});
|
|
398
|
-
} else if (reasoningMetadata?.redactedContent != null) {
|
|
399
|
-
bedrockContent.push({
|
|
400
|
-
reasoningContent: {
|
|
401
|
-
redactedContent: reasoningMetadata.redactedContent,
|
|
402
|
-
},
|
|
403
|
-
});
|
|
404
|
-
} else if (reasoningMetadata?.redactedData != null) {
|
|
405
|
-
bedrockContent.push({
|
|
406
|
-
reasoningContent: {
|
|
407
|
-
redactedReasoning: {
|
|
408
|
-
data: reasoningMetadata.redactedData,
|
|
409
|
-
},
|
|
410
|
-
},
|
|
411
|
-
});
|
|
435
|
+
const convertedPart = convertedReasoningContent[k];
|
|
436
|
+
if (convertedPart != null) {
|
|
437
|
+
bedrockContent.push(convertedPart);
|
|
412
438
|
}
|
|
413
439
|
// Unsigned reasoning is intentionally not replayed. Some
|
|
414
440
|
// Bedrock models (for example OpenAI gpt-oss) return reasoning
|
|
@@ -434,7 +460,9 @@ export async function convertToBedrockChatMessages(
|
|
|
434
460
|
pushCachePoint(bedrockContent, message.providerOptions);
|
|
435
461
|
}
|
|
436
462
|
|
|
437
|
-
|
|
463
|
+
if (bedrockContent.length > 0) {
|
|
464
|
+
messages.push({ role: 'assistant', content: bedrockContent });
|
|
465
|
+
}
|
|
438
466
|
|
|
439
467
|
break;
|
|
440
468
|
}
|