@ai-sdk/amazon-bedrock
Version:
The **[Amazon Bedrock provider](https://ai-sdk.dev/providers/ai-sdk-providers/amazon-bedrock)** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for the Amazon Bedrock [converse API](https://docs.aws.amazon.com/bedrock/latest/APIR
1,431 lines (1,416 loc) • 58.6 kB
JavaScript
// src/bedrock-provider.ts
import {
generateId,
loadOptionalSetting,
loadSetting,
withoutTrailingSlash
} from "@ai-sdk/provider-utils";
import { anthropicTools as anthropicTools2 } from "@ai-sdk/anthropic/internal";
// src/bedrock-chat-language-model.ts
import {
combineHeaders,
createJsonErrorResponseHandler,
createJsonResponseHandler,
parseProviderOptions as parseProviderOptions2,
postJsonToApi,
resolve
} from "@ai-sdk/provider-utils";
import { z as z3 } from "zod/v4";
// src/bedrock-api-types.ts
var BEDROCK_CACHE_POINT = {
cachePoint: { type: "default" }
};
var BEDROCK_STOP_REASONS = [
"stop",
"stop_sequence",
"end_turn",
"length",
"max_tokens",
"content-filter",
"content_filtered",
"guardrail_intervened",
"tool-calls",
"tool_use"
];
var BEDROCK_IMAGE_MIME_TYPES = {
"image/jpeg": "jpeg",
"image/png": "png",
"image/gif": "gif",
"image/webp": "webp"
};
var BEDROCK_DOCUMENT_MIME_TYPES = {
"application/pdf": "pdf",
"text/csv": "csv",
"application/msword": "doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
"application/vnd.ms-excel": "xls",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
"text/html": "html",
"text/plain": "txt",
"text/markdown": "md"
};
// src/bedrock-chat-options.ts
import { z } from "zod/v4";
var bedrockProviderOptions = z.object({
/**
* Additional inference parameters that the model supports,
* beyond the base set of inference parameters that Converse
* supports in the inferenceConfig field
*/
additionalModelRequestFields: z.record(z.string(), z.any()).optional(),
reasoningConfig: z.object({
type: z.union([z.literal("enabled"), z.literal("disabled")]).optional(),
budgetTokens: z.number().optional()
}).optional()
});
// src/bedrock-error.ts
import { z as z2 } from "zod/v4";
var BedrockErrorSchema = z2.object({
message: z2.string(),
type: z2.string().nullish()
});
// src/bedrock-event-stream-response-handler.ts
import { EmptyResponseBodyError } from "@ai-sdk/provider";
import {
safeParseJSON,
extractResponseHeaders,
safeValidateTypes
} from "@ai-sdk/provider-utils";
import { EventStreamCodec } from "@smithy/eventstream-codec";
import { toUtf8, fromUtf8 } from "@smithy/util-utf8";
var createBedrockEventStreamResponseHandler = (chunkSchema) => async ({ response }) => {
const responseHeaders = extractResponseHeaders(response);
if (response.body == null) {
throw new EmptyResponseBodyError({});
}
const codec = new EventStreamCodec(toUtf8, fromUtf8);
let buffer = new Uint8Array(0);
const textDecoder = new TextDecoder();
return {
responseHeaders,
value: response.body.pipeThrough(
new TransformStream({
async transform(chunk, controller) {
var _a, _b;
const newBuffer = new Uint8Array(buffer.length + chunk.length);
newBuffer.set(buffer);
newBuffer.set(chunk, buffer.length);
buffer = newBuffer;
while (buffer.length >= 4) {
const totalLength = new DataView(
buffer.buffer,
buffer.byteOffset,
buffer.byteLength
).getUint32(0, false);
if (buffer.length < totalLength) {
break;
}
try {
const subView = buffer.subarray(0, totalLength);
const decoded = codec.decode(subView);
buffer = buffer.slice(totalLength);
if (((_a = decoded.headers[":message-type"]) == null ? void 0 : _a.value) === "event") {
const data = textDecoder.decode(decoded.body);
const parsedDataResult = await safeParseJSON({ text: data });
if (!parsedDataResult.success) {
controller.enqueue(parsedDataResult);
break;
}
delete parsedDataResult.value.p;
let wrappedData = {
[(_b = decoded.headers[":event-type"]) == null ? void 0 : _b.value]: parsedDataResult.value
};
const validatedWrappedData = await safeValidateTypes({
value: wrappedData,
schema: chunkSchema
});
if (!validatedWrappedData.success) {
controller.enqueue(validatedWrappedData);
} else {
controller.enqueue({
success: true,
value: validatedWrappedData.value,
rawValue: wrappedData
});
}
}
} catch (e) {
break;
}
}
}
})
)
};
};
// src/bedrock-prepare-tools.ts
import {
UnsupportedFunctionalityError
} from "@ai-sdk/provider";
import { asSchema } from "@ai-sdk/provider-utils";
import {
anthropicTools,
prepareTools as prepareAnthropicTools
} from "@ai-sdk/anthropic/internal";
function prepareTools({
tools,
toolChoice,
modelId
}) {
const toolWarnings = [];
const betas = /* @__PURE__ */ new Set();
if (tools == null || tools.length === 0) {
return {
toolConfig: {},
additionalTools: void 0,
betas,
toolWarnings
};
}
const supportedTools = tools.filter((tool) => {
if (tool.type === "provider-defined" && tool.id === "anthropic.web_search_20250305") {
toolWarnings.push({
type: "unsupported-tool",
tool,
details: "The web_search_20250305 tool is not supported on Amazon Bedrock."
});
return false;
}
return true;
});
if (supportedTools.length === 0) {
return {
toolConfig: {},
additionalTools: void 0,
betas,
toolWarnings
};
}
const isAnthropicModel = modelId.includes("anthropic.");
const providerDefinedTools = supportedTools.filter(
(t) => t.type === "provider-defined"
);
const functionTools = supportedTools.filter((t) => t.type === "function");
let additionalTools = void 0;
const bedrockTools = [];
const usingAnthropicTools = isAnthropicModel && providerDefinedTools.length > 0;
if (usingAnthropicTools) {
if (functionTools.length > 0) {
toolWarnings.push({
type: "unsupported-setting",
setting: "tools",
details: "Mixed Anthropic provider-defined tools and standard function tools are not supported in a single call to Bedrock. Only Anthropic tools will be used."
});
}
const {
toolChoice: preparedAnthropicToolChoice,
toolWarnings: anthropicToolWarnings,
betas: anthropicBetas
} = prepareAnthropicTools({
tools: providerDefinedTools,
toolChoice
});
toolWarnings.push(...anthropicToolWarnings);
anthropicBetas.forEach((beta) => betas.add(beta));
if (preparedAnthropicToolChoice) {
additionalTools = {
tool_choice: preparedAnthropicToolChoice
};
}
for (const tool of providerDefinedTools) {
const toolFactory = Object.values(anthropicTools).find((factory) => {
const instance = factory({});
return instance.id === tool.id;
});
if (toolFactory != null) {
const fullToolDefinition = toolFactory({});
bedrockTools.push({
toolSpec: {
name: tool.name,
inputSchema: {
json: asSchema(fullToolDefinition.inputSchema).jsonSchema
}
}
});
} else {
toolWarnings.push({ type: "unsupported-tool", tool });
}
}
} else {
for (const tool of providerDefinedTools) {
toolWarnings.push({ type: "unsupported-tool", tool });
}
}
for (const tool of functionTools) {
bedrockTools.push({
toolSpec: {
name: tool.name,
description: tool.description,
inputSchema: {
json: tool.inputSchema
}
}
});
}
let bedrockToolChoice = void 0;
if (!usingAnthropicTools && bedrockTools.length > 0 && toolChoice) {
const type = toolChoice.type;
switch (type) {
case "auto":
bedrockToolChoice = { auto: {} };
break;
case "required":
bedrockToolChoice = { any: {} };
break;
case "none":
bedrockTools.length = 0;
bedrockToolChoice = void 0;
break;
case "tool":
bedrockToolChoice = { tool: { name: toolChoice.toolName } };
break;
default: {
const _exhaustiveCheck = type;
throw new UnsupportedFunctionalityError({
functionality: `tool choice type: ${_exhaustiveCheck}`
});
}
}
}
const toolConfig = bedrockTools.length > 0 ? { tools: bedrockTools, toolChoice: bedrockToolChoice } : {};
return {
toolConfig,
additionalTools,
betas,
toolWarnings
};
}
// src/convert-to-bedrock-chat-messages.ts
import {
UnsupportedFunctionalityError as UnsupportedFunctionalityError2
} from "@ai-sdk/provider";
import { convertToBase64, parseProviderOptions } from "@ai-sdk/provider-utils";
function getCachePoint(providerMetadata) {
var _a;
return (_a = providerMetadata == null ? void 0 : providerMetadata.bedrock) == null ? void 0 : _a.cachePoint;
}
async function convertToBedrockChatMessages(prompt) {
const blocks = groupIntoBlocks(prompt);
let system = [];
const messages = [];
let documentCounter = 0;
const generateDocumentName = () => `document-${++documentCounter}`;
for (let i = 0; i < blocks.length; i++) {
const block = blocks[i];
const isLastBlock = i === blocks.length - 1;
const type = block.type;
switch (type) {
case "system": {
if (messages.length > 0) {
throw new UnsupportedFunctionalityError2({
functionality: "Multiple system messages that are separated by user/assistant messages"
});
}
for (const message of block.messages) {
system.push({ text: message.content });
if (getCachePoint(message.providerOptions)) {
system.push(BEDROCK_CACHE_POINT);
}
}
break;
}
case "user": {
const bedrockContent = [];
for (const message of block.messages) {
const { role, content, providerOptions } = message;
switch (role) {
case "user": {
for (let j = 0; j < content.length; j++) {
const part = content[j];
switch (part.type) {
case "text": {
bedrockContent.push({
text: part.text
});
break;
}
case "file": {
if (part.data instanceof URL) {
throw new UnsupportedFunctionalityError2({
functionality: "File URL data"
});
}
if (part.mediaType.startsWith("image/")) {
bedrockContent.push({
image: {
format: getBedrockImageFormat(part.mediaType),
source: { bytes: convertToBase64(part.data) }
}
});
} else {
if (!part.mediaType) {
throw new UnsupportedFunctionalityError2({
functionality: "file without mime type",
message: "File mime type is required in user message part content"
});
}
bedrockContent.push({
document: {
format: getBedrockDocumentFormat(part.mediaType),
name: generateDocumentName(),
source: { bytes: convertToBase64(part.data) }
}
});
}
break;
}
}
}
break;
}
case "tool": {
for (const part of content) {
let toolResultContent;
const output = part.output;
switch (output.type) {
case "content": {
toolResultContent = output.value.map((contentPart) => {
switch (contentPart.type) {
case "text":
return { text: contentPart.text };
case "media":
if (!contentPart.mediaType.startsWith("image/")) {
throw new UnsupportedFunctionalityError2({
functionality: `media type: ${contentPart.mediaType}`
});
}
const format = getBedrockImageFormat(
contentPart.mediaType
);
return {
image: {
format,
source: { bytes: contentPart.data }
}
};
}
});
break;
}
case "text":
case "error-text":
toolResultContent = [{ text: output.value }];
break;
case "json":
case "error-json":
default:
toolResultContent = [
{ text: JSON.stringify(output.value) }
];
break;
}
bedrockContent.push({
toolResult: {
toolUseId: part.toolCallId,
content: toolResultContent
}
});
}
break;
}
default: {
const _exhaustiveCheck = role;
throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
}
}
if (getCachePoint(providerOptions)) {
bedrockContent.push(BEDROCK_CACHE_POINT);
}
}
messages.push({ role: "user", content: bedrockContent });
break;
}
case "assistant": {
const bedrockContent = [];
for (let j = 0; j < block.messages.length; j++) {
const message = block.messages[j];
const isLastMessage = j === block.messages.length - 1;
const { content } = message;
for (let k = 0; k < content.length; k++) {
const part = content[k];
const isLastContentPart = k === content.length - 1;
switch (part.type) {
case "text": {
bedrockContent.push({
text: (
// trim the last text part if it's the last message in the block
// because Bedrock does not allow trailing whitespace
// in pre-filled assistant responses
trimIfLast(
isLastBlock,
isLastMessage,
isLastContentPart,
part.text
)
)
});
break;
}
case "reasoning": {
const reasoningMetadata = await parseProviderOptions({
provider: "bedrock",
providerOptions: part.providerOptions,
schema: bedrockReasoningMetadataSchema
});
if (reasoningMetadata != null) {
if (reasoningMetadata.signature != null) {
bedrockContent.push({
reasoningContent: {
reasoningText: {
// trim the last text part if it's the last message in the block
// because Bedrock does not allow trailing whitespace
// in pre-filled assistant responses
text: trimIfLast(
isLastBlock,
isLastMessage,
isLastContentPart,
part.text
),
signature: reasoningMetadata.signature
}
}
});
} else if (reasoningMetadata.redactedData != null) {
bedrockContent.push({
reasoningContent: {
redactedReasoning: {
data: reasoningMetadata.redactedData
}
}
});
}
}
break;
}
case "tool-call": {
bedrockContent.push({
toolUse: {
toolUseId: part.toolCallId,
name: part.toolName,
input: part.input
}
});
break;
}
}
}
if (getCachePoint(message.providerOptions)) {
bedrockContent.push(BEDROCK_CACHE_POINT);
}
}
messages.push({ role: "assistant", content: bedrockContent });
break;
}
default: {
const _exhaustiveCheck = type;
throw new Error(`Unsupported type: ${_exhaustiveCheck}`);
}
}
}
return { system, messages };
}
function getBedrockImageFormat(mimeType) {
if (!mimeType) {
throw new UnsupportedFunctionalityError2({
functionality: "image without mime type",
message: "Image mime type is required in user message part content"
});
}
const format = BEDROCK_IMAGE_MIME_TYPES[mimeType];
if (!format) {
throw new UnsupportedFunctionalityError2({
functionality: `image mime type: ${mimeType}`,
message: `Unsupported image mime type: ${mimeType}, expected one of: ${Object.keys(BEDROCK_IMAGE_MIME_TYPES).join(", ")}`
});
}
return format;
}
function getBedrockDocumentFormat(mimeType) {
const format = BEDROCK_DOCUMENT_MIME_TYPES[mimeType];
if (!format) {
throw new UnsupportedFunctionalityError2({
functionality: `file mime type: ${mimeType}`,
message: `Unsupported file mime type: ${mimeType}, expected one of: ${Object.keys(BEDROCK_DOCUMENT_MIME_TYPES).join(", ")}`
});
}
return format;
}
function trimIfLast(isLastBlock, isLastMessage, isLastContentPart, text) {
return isLastBlock && isLastMessage && isLastContentPart ? text.trim() : text;
}
function groupIntoBlocks(prompt) {
const blocks = [];
let currentBlock = void 0;
for (const message of prompt) {
const { role } = message;
switch (role) {
case "system": {
if ((currentBlock == null ? void 0 : currentBlock.type) !== "system") {
currentBlock = { type: "system", messages: [] };
blocks.push(currentBlock);
}
currentBlock.messages.push(message);
break;
}
case "assistant": {
if ((currentBlock == null ? void 0 : currentBlock.type) !== "assistant") {
currentBlock = { type: "assistant", messages: [] };
blocks.push(currentBlock);
}
currentBlock.messages.push(message);
break;
}
case "user": {
if ((currentBlock == null ? void 0 : currentBlock.type) !== "user") {
currentBlock = { type: "user", messages: [] };
blocks.push(currentBlock);
}
currentBlock.messages.push(message);
break;
}
case "tool": {
if ((currentBlock == null ? void 0 : currentBlock.type) !== "user") {
currentBlock = { type: "user", messages: [] };
blocks.push(currentBlock);
}
currentBlock.messages.push(message);
break;
}
default: {
const _exhaustiveCheck = role;
throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
}
}
}
return blocks;
}
// src/map-bedrock-finish-reason.ts
function mapBedrockFinishReason(finishReason) {
switch (finishReason) {
case "stop_sequence":
case "end_turn":
return "stop";
case "max_tokens":
return "length";
case "content_filtered":
case "guardrail_intervened":
return "content-filter";
case "tool_use":
return "tool-calls";
default:
return "unknown";
}
}
// src/bedrock-chat-language-model.ts
var BedrockChatLanguageModel = class {
constructor(modelId, config) {
this.modelId = modelId;
this.config = config;
this.specificationVersion = "v2";
this.provider = "amazon-bedrock";
this.supportedUrls = {
// no supported urls for bedrock
};
}
async getArgs({
prompt,
maxOutputTokens,
temperature,
topP,
topK,
frequencyPenalty,
presencePenalty,
stopSequences,
responseFormat,
seed,
tools,
toolChoice,
providerOptions
}) {
var _a, _b, _c, _d, _e, _f;
const bedrockOptions = (_a = await parseProviderOptions2({
provider: "bedrock",
providerOptions,
schema: bedrockProviderOptions
})) != null ? _a : {};
const warnings = [];
if (frequencyPenalty != null) {
warnings.push({
type: "unsupported-setting",
setting: "frequencyPenalty"
});
}
if (presencePenalty != null) {
warnings.push({
type: "unsupported-setting",
setting: "presencePenalty"
});
}
if (seed != null) {
warnings.push({
type: "unsupported-setting",
setting: "seed"
});
}
if (responseFormat != null && responseFormat.type !== "text" && responseFormat.type !== "json") {
warnings.push({
type: "unsupported-setting",
setting: "responseFormat",
details: "Only text and json response formats are supported."
});
}
if (tools != null && (responseFormat == null ? void 0 : responseFormat.type) === "json") {
if (tools.length > 0) {
warnings.push({
type: "other",
message: "JSON response format does not support tools. The provided tools are ignored."
});
}
}
const jsonResponseTool = (responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null ? {
type: "function",
name: "json",
description: "Respond with a JSON object.",
inputSchema: responseFormat.schema
} : void 0;
const { toolConfig, additionalTools, toolWarnings, betas } = prepareTools({
tools: jsonResponseTool ? [jsonResponseTool, ...tools != null ? tools : []] : tools,
toolChoice: jsonResponseTool != null ? { type: "tool", toolName: jsonResponseTool.name } : toolChoice,
modelId: this.modelId
});
warnings.push(...toolWarnings);
if (additionalTools) {
bedrockOptions.additionalModelRequestFields = {
...bedrockOptions.additionalModelRequestFields,
...additionalTools
};
}
const isThinking = ((_b = bedrockOptions.reasoningConfig) == null ? void 0 : _b.type) === "enabled";
const thinkingBudget = (_c = bedrockOptions.reasoningConfig) == null ? void 0 : _c.budgetTokens;
const inferenceConfig = {
...maxOutputTokens != null && { maxOutputTokens },
...temperature != null && { temperature },
...topP != null && { topP },
...topK != null && { topK },
...stopSequences != null && { stopSequences }
};
if (isThinking && thinkingBudget != null) {
if (inferenceConfig.maxOutputTokens != null) {
inferenceConfig.maxOutputTokens += thinkingBudget;
} else {
inferenceConfig.maxOutputTokens = thinkingBudget + 4096;
}
bedrockOptions.additionalModelRequestFields = {
...bedrockOptions.additionalModelRequestFields,
thinking: {
type: (_d = bedrockOptions.reasoningConfig) == null ? void 0 : _d.type,
budget_tokens: thinkingBudget
}
};
}
if (isThinking && inferenceConfig.temperature != null) {
delete inferenceConfig.temperature;
warnings.push({
type: "unsupported-setting",
setting: "temperature",
details: "temperature is not supported when thinking is enabled"
});
}
if (isThinking && inferenceConfig.topP != null) {
delete inferenceConfig.topP;
warnings.push({
type: "unsupported-setting",
setting: "topP",
details: "topP is not supported when thinking is enabled"
});
}
if (isThinking && inferenceConfig.topK != null) {
delete inferenceConfig.topK;
warnings.push({
type: "unsupported-setting",
setting: "topK",
details: "topK is not supported when thinking is enabled"
});
}
const hasAnyTools = ((_f = (_e = toolConfig.tools) == null ? void 0 : _e.length) != null ? _f : 0) > 0 || additionalTools;
let filteredPrompt = prompt;
if (!hasAnyTools) {
const hasToolContent = prompt.some(
(message) => "content" in message && Array.isArray(message.content) && message.content.some(
(part) => part.type === "tool-call" || part.type === "tool-result"
)
);
if (hasToolContent) {
filteredPrompt = prompt.map(
(message) => message.role === "system" ? message : {
...message,
content: message.content.filter(
(part) => part.type !== "tool-call" && part.type !== "tool-result"
)
}
).filter(
(message) => message.role === "system" || message.content.length > 0
);
warnings.push({
type: "unsupported-setting",
setting: "toolContent",
details: "Tool calls and results removed from conversation because Bedrock does not support tool content without active tools."
});
}
}
const { system, messages } = await convertToBedrockChatMessages(filteredPrompt);
const { reasoningConfig: _, ...filteredBedrockOptions } = (providerOptions == null ? void 0 : providerOptions.bedrock) || {};
return {
command: {
system,
messages,
additionalModelRequestFields: bedrockOptions.additionalModelRequestFields,
...Object.keys(inferenceConfig).length > 0 && {
inferenceConfig
},
...filteredBedrockOptions,
...toolConfig.tools !== void 0 && toolConfig.tools.length > 0 ? { toolConfig } : {}
},
warnings,
usesJsonResponseTool: jsonResponseTool != null,
betas
};
}
async getHeaders({
betas,
headers
}) {
return combineHeaders(
await resolve(this.config.headers),
betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {},
headers
);
}
async doGenerate(options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
const {
command: args,
warnings,
usesJsonResponseTool,
betas
} = await this.getArgs(options);
const url = `${this.getUrl(this.modelId)}/converse`;
const { value: response, responseHeaders } = await postJsonToApi({
url,
headers: await this.getHeaders({ betas, headers: options.headers }),
body: args,
failedResponseHandler: createJsonErrorResponseHandler({
errorSchema: BedrockErrorSchema,
errorToMessage: (error) => {
var _a2;
return `${(_a2 = error.message) != null ? _a2 : "Unknown error"}`;
}
}),
successfulResponseHandler: createJsonResponseHandler(
BedrockResponseSchema
),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
const content = [];
for (const part of response.output.message.content) {
if (part.text) {
if (!usesJsonResponseTool) {
content.push({ type: "text", text: part.text });
}
}
if (part.reasoningContent) {
if ("reasoningText" in part.reasoningContent) {
const reasoning = {
type: "reasoning",
text: part.reasoningContent.reasoningText.text
};
if (part.reasoningContent.reasoningText.signature) {
reasoning.providerMetadata = {
bedrock: {
signature: part.reasoningContent.reasoningText.signature
}
};
}
content.push(reasoning);
} else if ("redactedReasoning" in part.reasoningContent) {
content.push({
type: "reasoning",
text: "",
providerMetadata: {
bedrock: {
redactedData: (_a = part.reasoningContent.redactedReasoning.data) != null ? _a : ""
}
}
});
}
}
if (part.toolUse) {
content.push(
// when a json response tool is used, the tool call becomes the text:
usesJsonResponseTool ? {
type: "text",
text: JSON.stringify(part.toolUse.input)
} : {
type: "tool-call",
toolCallId: (_c = (_b = part.toolUse) == null ? void 0 : _b.toolUseId) != null ? _c : this.config.generateId(),
toolName: (_e = (_d = part.toolUse) == null ? void 0 : _d.name) != null ? _e : `tool-${this.config.generateId()}`,
input: JSON.stringify((_g = (_f = part.toolUse) == null ? void 0 : _f.input) != null ? _g : "")
}
);
}
}
const providerMetadata = response.trace || response.usage || usesJsonResponseTool ? {
bedrock: {
...response.trace && typeof response.trace === "object" ? { trace: response.trace } : {},
...((_h = response.usage) == null ? void 0 : _h.cacheWriteInputTokens) != null && {
usage: {
cacheWriteInputTokens: response.usage.cacheWriteInputTokens
}
},
...usesJsonResponseTool && { isJsonResponseFromTool: true }
}
} : void 0;
return {
content,
finishReason: mapBedrockFinishReason(
response.stopReason
),
usage: {
inputTokens: (_i = response.usage) == null ? void 0 : _i.inputTokens,
outputTokens: (_j = response.usage) == null ? void 0 : _j.outputTokens,
totalTokens: ((_k = response.usage) == null ? void 0 : _k.inputTokens) + ((_l = response.usage) == null ? void 0 : _l.outputTokens),
cachedInputTokens: (_n = (_m = response.usage) == null ? void 0 : _m.cacheReadInputTokens) != null ? _n : void 0
},
response: {
// TODO add id, timestamp, etc
headers: responseHeaders
},
warnings,
...providerMetadata && { providerMetadata }
};
}
async doStream(options) {
const {
command: args,
warnings,
usesJsonResponseTool,
betas
} = await this.getArgs(options);
const url = `${this.getUrl(this.modelId)}/converse-stream`;
const { value: response, responseHeaders } = await postJsonToApi({
url,
headers: await this.getHeaders({ betas, headers: options.headers }),
body: args,
failedResponseHandler: createJsonErrorResponseHandler({
errorSchema: BedrockErrorSchema,
errorToMessage: (error) => `${error.type}: ${error.message}`
}),
successfulResponseHandler: createBedrockEventStreamResponseHandler(BedrockStreamSchema),
abortSignal: options.abortSignal,
fetch: this.config.fetch
});
let finishReason = "unknown";
const usage = {
inputTokens: void 0,
outputTokens: void 0,
totalTokens: void 0
};
let providerMetadata = void 0;
const contentBlocks = {};
return {
stream: response.pipeThrough(
new TransformStream({
start(controller) {
controller.enqueue({ type: "stream-start", warnings });
},
transform(chunk, controller) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
function enqueueError(bedrockError) {
finishReason = "error";
controller.enqueue({ type: "error", error: bedrockError });
}
if (options.includeRawChunks) {
controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
}
if (!chunk.success) {
enqueueError(chunk.error);
return;
}
const value = chunk.value;
if (value.internalServerException) {
enqueueError(value.internalServerException);
return;
}
if (value.modelStreamErrorException) {
enqueueError(value.modelStreamErrorException);
return;
}
if (value.throttlingException) {
enqueueError(value.throttlingException);
return;
}
if (value.validationException) {
enqueueError(value.validationException);
return;
}
if (value.messageStop) {
finishReason = mapBedrockFinishReason(
value.messageStop.stopReason
);
}
if (value.metadata) {
usage.inputTokens = (_b = (_a = value.metadata.usage) == null ? void 0 : _a.inputTokens) != null ? _b : usage.inputTokens;
usage.outputTokens = (_d = (_c = value.metadata.usage) == null ? void 0 : _c.outputTokens) != null ? _d : usage.outputTokens;
usage.totalTokens = ((_e = usage.inputTokens) != null ? _e : 0) + ((_f = usage.outputTokens) != null ? _f : 0);
usage.cachedInputTokens = (_h = (_g = value.metadata.usage) == null ? void 0 : _g.cacheReadInputTokens) != null ? _h : usage.cachedInputTokens;
const cacheUsage = ((_i = value.metadata.usage) == null ? void 0 : _i.cacheWriteInputTokens) != null ? {
usage: {
cacheWriteInputTokens: value.metadata.usage.cacheWriteInputTokens
}
} : void 0;
const trace = value.metadata.trace ? {
trace: value.metadata.trace
} : void 0;
if (cacheUsage || trace || usesJsonResponseTool) {
providerMetadata = {
bedrock: {
...cacheUsage,
...trace,
...usesJsonResponseTool && {
isJsonResponseFromTool: true
}
}
};
}
}
if (((_j = value.contentBlockStart) == null ? void 0 : _j.contentBlockIndex) != null && !((_l = (_k = value.contentBlockStart) == null ? void 0 : _k.start) == null ? void 0 : _l.toolUse)) {
const blockIndex = value.contentBlockStart.contentBlockIndex;
contentBlocks[blockIndex] = { type: "text" };
controller.enqueue({
type: "text-start",
id: String(blockIndex)
});
}
if (((_m = value.contentBlockDelta) == null ? void 0 : _m.delta) && "text" in value.contentBlockDelta.delta && value.contentBlockDelta.delta.text) {
const blockIndex = value.contentBlockDelta.contentBlockIndex || 0;
if (contentBlocks[blockIndex] == null) {
contentBlocks[blockIndex] = { type: "text" };
if (!usesJsonResponseTool) {
controller.enqueue({
type: "text-start",
id: String(blockIndex)
});
}
}
if (!usesJsonResponseTool) {
controller.enqueue({
type: "text-delta",
id: String(blockIndex),
delta: value.contentBlockDelta.delta.text
});
}
}
if (((_n = value.contentBlockStop) == null ? void 0 : _n.contentBlockIndex) != null) {
const blockIndex = value.contentBlockStop.contentBlockIndex;
const contentBlock = contentBlocks[blockIndex];
if (contentBlock != null) {
if (contentBlock.type === "reasoning") {
controller.enqueue({
type: "reasoning-end",
id: String(blockIndex)
});
} else if (contentBlock.type === "text") {
if (!usesJsonResponseTool) {
controller.enqueue({
type: "text-end",
id: String(blockIndex)
});
}
} else if (contentBlock.type === "tool-call") {
if (usesJsonResponseTool) {
controller.enqueue({
type: "text-start",
id: String(blockIndex)
});
controller.enqueue({
type: "text-delta",
id: String(blockIndex),
delta: contentBlock.jsonText
});
controller.enqueue({
type: "text-end",
id: String(blockIndex)
});
} else {
controller.enqueue({
type: "tool-input-end",
id: contentBlock.toolCallId
});
controller.enqueue({
type: "tool-call",
toolCallId: contentBlock.toolCallId,
toolName: contentBlock.toolName,
input: contentBlock.jsonText
});
}
}
delete contentBlocks[blockIndex];
}
}
if (((_o = value.contentBlockDelta) == null ? void 0 : _o.delta) && "reasoningContent" in value.contentBlockDelta.delta && value.contentBlockDelta.delta.reasoningContent) {
const blockIndex = value.contentBlockDelta.contentBlockIndex || 0;
const reasoningContent = value.contentBlockDelta.delta.reasoningContent;
if ("text" in reasoningContent && reasoningContent.text) {
if (contentBlocks[blockIndex] == null) {
contentBlocks[blockIndex] = { type: "reasoning" };
controller.enqueue({
type: "reasoning-start",
id: String(blockIndex)
});
}
controller.enqueue({
type: "reasoning-delta",
id: String(blockIndex),
delta: reasoningContent.text
});
} else if ("signature" in reasoningContent && reasoningContent.signature) {
controller.enqueue({
type: "reasoning-delta",
id: String(blockIndex),
delta: "",
providerMetadata: {
bedrock: {
signature: reasoningContent.signature
}
}
});
} else if ("data" in reasoningContent && reasoningContent.data) {
controller.enqueue({
type: "reasoning-delta",
id: String(blockIndex),
delta: "",
providerMetadata: {
bedrock: {
redactedData: reasoningContent.data
}
}
});
}
}
const contentBlockStart = value.contentBlockStart;
if (((_p = contentBlockStart == null ? void 0 : contentBlockStart.start) == null ? void 0 : _p.toolUse) != null) {
const toolUse = contentBlockStart.start.toolUse;
const blockIndex = contentBlockStart.contentBlockIndex;
contentBlocks[blockIndex] = {
type: "tool-call",
toolCallId: toolUse.toolUseId,
toolName: toolUse.name,
jsonText: ""
};
if (!usesJsonResponseTool) {
controller.enqueue({
type: "tool-input-start",
id: toolUse.toolUseId,
toolName: toolUse.name
});
}
}
const contentBlockDelta = value.contentBlockDelta;
if ((contentBlockDelta == null ? void 0 : contentBlockDelta.delta) && "toolUse" in contentBlockDelta.delta && contentBlockDelta.delta.toolUse) {
const blockIndex = contentBlockDelta.contentBlockIndex;
const contentBlock = contentBlocks[blockIndex];
if ((contentBlock == null ? void 0 : contentBlock.type) === "tool-call") {
const delta = (_q = contentBlockDelta.delta.toolUse.input) != null ? _q : "";
if (!usesJsonResponseTool) {
controller.enqueue({
type: "tool-input-delta",
id: contentBlock.toolCallId,
delta
});
}
contentBlock.jsonText += delta;
}
}
},
flush(controller) {
controller.enqueue({
type: "finish",
finishReason,
usage,
...providerMetadata && { providerMetadata }
});
}
})
),
// TODO request?
response: { headers: responseHeaders }
};
}
getUrl(modelId) {
const encodedModelId = encodeURIComponent(modelId);
return `${this.config.baseUrl()}/model/${encodedModelId}`;
}
};
var BedrockStopReasonSchema = z3.union([
z3.enum(BEDROCK_STOP_REASONS),
z3.string()
]);
var BedrockToolUseSchema = z3.object({
toolUseId: z3.string(),
name: z3.string(),
input: z3.unknown()
});
var BedrockReasoningTextSchema = z3.object({
signature: z3.string().nullish(),
text: z3.string()
});
var BedrockRedactedReasoningSchema = z3.object({
data: z3.string()
});
var BedrockResponseSchema = z3.object({
metrics: z3.object({
latencyMs: z3.number()
}).nullish(),
output: z3.object({
message: z3.object({
content: z3.array(
z3.object({
text: z3.string().nullish(),
toolUse: BedrockToolUseSchema.nullish(),
reasoningContent: z3.union([
z3.object({
reasoningText: BedrockReasoningTextSchema
}),
z3.object({
redactedReasoning: BedrockRedactedReasoningSchema
})
]).nullish()
})
),
role: z3.string()
})
}),
stopReason: BedrockStopReasonSchema,
trace: z3.unknown().nullish(),
usage: z3.object({
inputTokens: z3.number(),
outputTokens: z3.number(),
totalTokens: z3.number(),
cacheReadInputTokens: z3.number().nullish(),
cacheWriteInputTokens: z3.number().nullish()
})
});
var BedrockStreamSchema = z3.object({
contentBlockDelta: z3.object({
contentBlockIndex: z3.number(),
delta: z3.union([
z3.object({ text: z3.string() }),
z3.object({ toolUse: z3.object({ input: z3.string() }) }),
z3.object({
reasoningContent: z3.object({ text: z3.string() })
}),
z3.object({
reasoningContent: z3.object({
signature: z3.string()
})
}),
z3.object({
reasoningContent: z3.object({ data: z3.string() })
})
]).nullish()
}).nullish(),
contentBlockStart: z3.object({
contentBlockIndex: z3.number(),
start: z3.object({
toolUse: BedrockToolUseSchema.nullish()
}).nullish()
}).nullish(),
contentBlockStop: z3.object({
contentBlockIndex: z3.number()
}).nullish(),
internalServerException: z3.record(z3.string(), z3.unknown()).nullish(),
messageStop: z3.object({
additionalModelResponseFields: z3.record(z3.string(), z3.unknown()).nullish(),
stopReason: BedrockStopReasonSchema
}).nullish(),
metadata: z3.object({
trace: z3.unknown().nullish(),
usage: z3.object({
cacheReadInputTokens: z3.number().nullish(),
cacheWriteInputTokens: z3.number().nullish(),
inputTokens: z3.number(),
outputTokens: z3.number()
}).nullish()
}).nullish(),
modelStreamErrorException: z3.record(z3.string(), z3.unknown()).nullish(),
throttlingException: z3.record(z3.string(), z3.unknown()).nullish(),
validationException: z3.record(z3.string(), z3.unknown()).nullish()
});
var bedrockReasoningMetadataSchema = z3.object({
signature: z3.string().optional(),
redactedData: z3.string().optional()
});
// src/bedrock-embedding-model.ts
import {
TooManyEmbeddingValuesForCallError
} from "@ai-sdk/provider";
import {
combineHeaders as combineHeaders2,
createJsonErrorResponseHandler as createJsonErrorResponseHandler2,
createJsonResponseHandler as createJsonResponseHandler2,
parseProviderOptions as parseProviderOptions3,
postJsonToApi as postJsonToApi2,
resolve as resolve2
} from "@ai-sdk/provider-utils";
// src/bedrock-embedding-options.ts
import { z as z4 } from "zod/v4";
var bedrockEmbeddingProviderOptions = z4.object({
/**
The number of dimensions the resulting output embeddings should have (defaults to 1024).
Only supported in amazon.titan-embed-text-v2:0.
*/
dimensions: z4.union([z4.literal(1024), z4.literal(512), z4.literal(256)]).optional(),
/**
Flag indicating whether or not to normalize the output embeddings. Defaults to true
Only supported in amazon.titan-embed-text-v2:0.
*/
normalize: z4.boolean().optional()
});
// src/bedrock-embedding-model.ts
import { z as z5 } from "zod/v4";
var BedrockEmbeddingModel = class {
constructor(modelId, config) {
this.modelId = modelId;
this.config = config;
this.specificationVersion = "v2";
this.provider = "amazon-bedrock";
this.maxEmbeddingsPerCall = 1;
this.supportsParallelCalls = true;
}
getUrl(modelId) {
const encodedModelId = encodeURIComponent(modelId);
return `${this.config.baseUrl()}/model/${encodedModelId}/invoke`;
}
async doEmbed({
values,
headers,
abortSignal,
providerOptions
}) {
var _a;
if (values.length > this.maxEmbeddingsPerCall) {
throw new TooManyEmbeddingValuesForCallError({
provider: this.provider,
modelId: this.modelId,
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
values
});
}
const bedrockOptions = (_a = await parseProviderOptions3({
provider: "bedrock",
providerOptions,
schema: bedrockEmbeddingProviderOptions
})) != null ? _a : {};
const args = {
inputText: values[0],
dimensions: bedrockOptions.dimensions,
normalize: bedrockOptions.normalize
};
const url = this.getUrl(this.modelId);
const { value: response } = await postJsonToApi2({
url,
headers: await resolve2(
combineHeaders2(await resolve2(this.config.headers), headers)
),
body: args,
failedResponseHandler: createJsonErrorResponseHandler2({
errorSchema: BedrockErrorSchema,
errorToMessage: (error) => `${error.type}: ${error.message}`
}),
successfulResponseHandler: createJsonResponseHandler2(
BedrockEmbeddingResponseSchema
),
fetch: this.config.fetch,
abortSignal
});
return {
embeddings: [response.embedding],
usage: { tokens: response.inputTextTokenCount }
};
}
};
var BedrockEmbeddingResponseSchema = z5.object({
embedding: z5.array(z5.number()),
inputTextTokenCount: z5.number()
});
// src/bedrock-image-model.ts
import {
combineHeaders as combineHeaders3,
createJsonErrorResponseHandler as createJsonErrorResponseHandler3,
createJsonResponseHandler as createJsonResponseHandler3,
postJsonToApi as postJsonToApi3,
resolve as resolve3
} from "@ai-sdk/provider-utils";
// src/bedrock-image-settings.ts
var modelMaxImagesPerCall = {
"amazon.nova-canvas-v1:0": 5
};
// src/bedrock-image-model.ts
import { z as z6 } from "zod/v4";
var BedrockImageModel = class {
constructor(modelId, config) {
this.modelId = modelId;
this.config = config;
this.specificationVersion = "v2";
this.provider = "amazon-bedrock";
}
get maxImagesPerCall() {
var _a;
return (_a = modelMaxImagesPerCall[this.modelId]) != null ? _a : 1;
}
getUrl(modelId) {
const encodedModelId = encodeURIComponent(modelId);
return `${this.config.baseUrl()}/model/${encodedModelId}/invoke`;
}
async doGenerate({
prompt,
n,
size,
aspectRatio,
seed,
providerOptions,
headers,
abortSignal
}) {
var _a, _b, _c, _d, _e, _f, _g;
const warnings = [];
const [width, height] = size ? size.split("x").map(Number) : [];
const args = {
taskType: "TEXT_IMAGE",
textToImageParams: {
text: prompt,
...((_a = providerOptions == null ? void 0 : providerOptions.bedrock) == null ? void 0 : _a.negativeText) ? {
negativeText: providerOptions.bedrock.negativeText
} : {},
...((_b = providerOptions == null ? void 0 : providerOptions.bedrock) == null ? void 0 : _b.style) ? {
style: providerOptions.bedrock.style
} : {}
},
imageGenerationConfig: {
...width ? { width } : {},
...height ? { height } : {},
...seed ? { seed } : {},
...n ? { numberOfImages: n } : {},
...((_c = providerOptions == null ? void 0 : providerOptions.bedrock) == null ? void 0 : _c.quality) ? { quality: providerOptions.bedrock.quality } : {},
...((_d = providerOptions == null ? void 0 : providerOptions.bedroc