LibreChat/api/server/services/Endpoints/bedrock/options.js
Dustin Healy 66dc48c8a0 🔧 WIP: Enhance Bedrock endpoint configuration with user-provided credentials. (Still needs to implement user_provided bearer token support, but the UI is there for it)
- Added support for user-provided AWS credentials (Access Key ID, Secret Access Key, Session Token, Bearer Token) in the Bedrock endpoint configuration.
- Localized new strings for Bedrock configuration in translation files.
2025-07-26 18:14:02 -07:00

121 lines
3.2 KiB
JavaScript

const { HttpsProxyAgent } = require('https-proxy-agent');
const { createHandleLLMNewToken } = require('@librechat/api');
const {
AuthType,
Constants,
EModelEndpoint,
bedrockInputParser,
bedrockOutputParser,
removeNullishValues,
} = require('librechat-data-provider');
const { getUserKeyValues, checkUserKeyExpiry } = require('~/server/services/UserService');
const getOptions = async ({ req, overrideModel, endpointOption }) => {
const {
BEDROCK_AWS_SECRET_ACCESS_KEY,
BEDROCK_AWS_ACCESS_KEY_ID,
BEDROCK_AWS_SESSION_TOKEN,
BEDROCK_AWS_BEARER_TOKEN,
BEDROCK_REVERSE_PROXY,
BEDROCK_AWS_DEFAULT_REGION,
PROXY,
} = process.env;
const expiresAt = req.body.key;
const isUserProvided =
BEDROCK_AWS_SECRET_ACCESS_KEY === AuthType.USER_PROVIDED ||
BEDROCK_AWS_BEARER_TOKEN === AuthType.USER_PROVIDED;
let userValues = null;
if (isUserProvided) {
if (expiresAt) {
checkUserKeyExpiry(expiresAt, EModelEndpoint.bedrock);
}
userValues = await getUserKeyValues({ userId: req.user.id, name: EModelEndpoint.bedrock });
}
let credentials;
if (isUserProvided) {
credentials = JSON.parse(userValues.apiKey);
} else if (BEDROCK_AWS_BEARER_TOKEN) {
credentials = { bearerToken: BEDROCK_AWS_BEARER_TOKEN };
} else {
credentials = {
accessKeyId: BEDROCK_AWS_ACCESS_KEY_ID,
secretAccessKey: BEDROCK_AWS_SECRET_ACCESS_KEY,
...(BEDROCK_AWS_SESSION_TOKEN && { sessionToken: BEDROCK_AWS_SESSION_TOKEN }),
};
}
if (!credentials) {
throw new Error('Bedrock credentials not provided. Please provide them again.');
}
if (
!isUserProvided &&
!credentials.bearerToken &&
(credentials.accessKeyId === undefined || credentials.accessKeyId === '') &&
(credentials.secretAccessKey === undefined || credentials.secretAccessKey === '')
) {
credentials = undefined;
}
if (expiresAt && isUserProvided) {
checkUserKeyExpiry(expiresAt, EModelEndpoint.bedrock);
}
/** @type {number} */
let streamRate = Constants.DEFAULT_STREAM_RATE;
/** @type {undefined | TBaseEndpoint} */
const bedrockConfig = req.app.locals[EModelEndpoint.bedrock];
if (bedrockConfig && bedrockConfig.streamRate) {
streamRate = bedrockConfig.streamRate;
}
/** @type {undefined | TBaseEndpoint} */
const allConfig = req.app.locals.all;
if (allConfig && allConfig.streamRate) {
streamRate = allConfig.streamRate;
}
/** @type {BedrockClientOptions} */
const requestOptions = {
model: overrideModel ?? endpointOption?.model,
region: BEDROCK_AWS_DEFAULT_REGION,
};
const configOptions = {};
if (PROXY) {
/** NOTE: NOT SUPPORTED BY BEDROCK */
configOptions.httpAgent = new HttpsProxyAgent(PROXY);
}
const llmConfig = bedrockOutputParser(
bedrockInputParser.parse(
removeNullishValues(Object.assign(requestOptions, endpointOption?.model_parameters ?? {})),
),
);
if (credentials) {
llmConfig.credentials = credentials;
}
if (BEDROCK_REVERSE_PROXY) {
llmConfig.endpointHost = BEDROCK_REVERSE_PROXY;
}
llmConfig.callbacks = [
{
handleLLMNewToken: createHandleLLMNewToken(streamRate),
},
];
return {
/** @type {BedrockClientOptions} */
llmConfig,
configOptions,
};
};
module.exports = getOptions;