mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-05-13 16:07:30 +00:00
When GOOGLE_KEY=user_provided is set as an endpoint config, the loadAuthValues() function in credentials.js would pass the literal string 'user_provided' to tools via the || fallback chain. This caused Gemini Image Tools to fail at runtime with an invalid API key error, as initializeGeminiClient() received the sentinel value instead of a real key. The fix aligns loadAuthValues() with checkPluginAuth() in format.ts, which already correctly excludes user_provided and empty/whitespace values. Now loadAuthValues() skips these values and continues to the next field in the fallback chain or falls through to user DB values. Added regression tests covering: - user_provided sentinel is skipped, DB value used instead - Fallback chain continues past user_provided to next field - Empty and whitespace env values are skipped - Real env values are returned correctly - Optional fields with sentinel values handled gracefully
58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
const { AuthType } = require('librechat-data-provider');
|
|
const { getUserPluginAuthValue } = require('~/server/services/PluginService');
|
|
|
|
/**
|
|
*
|
|
* @param {Object} params
|
|
* @param {string} params.userId
|
|
* @param {string[]} params.authFields
|
|
* @param {Set<string>} [params.optional]
|
|
* @param {boolean} [params.throwError]
|
|
* @returns
|
|
*/
|
|
const loadAuthValues = async ({ userId, authFields, optional, throwError = true }) => {
|
|
let authValues = {};
|
|
|
|
/**
|
|
* Finds the first non-empty value for the given authentication field, supporting alternate fields.
|
|
* @param {string[]} fields Array of strings representing the authentication fields. Supports alternate fields delimited by "||".
|
|
* @returns {Promise<{ authField: string, authValue: string} | null>} An object containing the authentication field and value, or null if not found.
|
|
*/
|
|
const findAuthValue = async (fields) => {
|
|
for (const field of fields) {
|
|
const envValue = process.env[field];
|
|
if (envValue && envValue.trim() !== '' && envValue !== AuthType.USER_PROVIDED) {
|
|
return { authField: field, authValue: envValue };
|
|
}
|
|
let value;
|
|
try {
|
|
value = await getUserPluginAuthValue(userId, field, throwError);
|
|
} catch (err) {
|
|
if (optional && optional.has(field)) {
|
|
return { authField: field, authValue: undefined };
|
|
}
|
|
if (field === fields[fields.length - 1]) {
|
|
throw err;
|
|
}
|
|
}
|
|
if (value) {
|
|
return { authField: field, authValue: value };
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
for (let authField of authFields) {
|
|
const fields = authField.split('||');
|
|
const result = await findAuthValue(fields);
|
|
if (result) {
|
|
authValues[result.authField] = result.authValue;
|
|
}
|
|
}
|
|
|
|
return authValues;
|
|
};
|
|
|
|
module.exports = {
|
|
loadAuthValues,
|
|
};
|