From 20100e120bfd4d2571a8a759104036110a014692 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sun, 29 Jun 2025 17:09:37 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=91=20feat:=20Set=20Google=20Service?= =?UTF-8?q?=20Key=20File=20Path=20(#8130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/Config/loadAsyncEndpoints.js | 32 +++++++++++++------ .../services/Endpoints/google/initialize.js | 16 +++++++++- packages/api/src/files/mistral/crud.ts | 13 +++++--- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/api/server/services/Config/loadAsyncEndpoints.js b/api/server/services/Config/loadAsyncEndpoints.js index 0282146cd1..edded906d8 100644 --- a/api/server/services/Config/loadAsyncEndpoints.js +++ b/api/server/services/Config/loadAsyncEndpoints.js @@ -1,3 +1,5 @@ +const fs = require('fs'); +const path = require('path'); const { EModelEndpoint } = require('librechat-data-provider'); const { isUserProvided } = require('~/server/utils'); const { config } = require('./EndpointService'); @@ -11,9 +13,21 @@ const { openAIApiKey, azureOpenAIApiKey, useAzurePlugins, userProvidedOpenAI, go async function loadAsyncEndpoints(req) { let i = 0; let serviceKey, googleUserProvides; + const serviceKeyPath = + process.env.GOOGLE_SERVICE_KEY_FILE_PATH || + path.join(__dirname, '../../..', 'data', 'auth.json'); + try { - serviceKey = require('~/data/auth.json'); - } catch (e) { + if (process.env.GOOGLE_SERVICE_KEY_FILE_PATH) { + const absolutePath = path.isAbsolute(serviceKeyPath) + ? serviceKeyPath + : path.resolve(serviceKeyPath); + const fileContent = fs.readFileSync(absolutePath, 'utf8'); + serviceKey = JSON.parse(fileContent); + } else { + serviceKey = require('~/data/auth.json'); + } + } catch { if (i === 0) { i++; } @@ -32,14 +46,14 @@ async function loadAsyncEndpoints(req) { const gptPlugins = useAzure || openAIApiKey || azureOpenAIApiKey ? { - availableAgents: ['classic', 'functions'], - userProvide: useAzure ? false : userProvidedOpenAI, - userProvideURL: useAzure - ? false - : config[EModelEndpoint.openAI]?.userProvideURL || + availableAgents: ['classic', 'functions'], + userProvide: useAzure ? false : userProvidedOpenAI, + userProvideURL: useAzure + ? false + : config[EModelEndpoint.openAI]?.userProvideURL || config[EModelEndpoint.azureOpenAI]?.userProvideURL, - azure: useAzurePlugins || useAzure, - } + azure: useAzurePlugins || useAzure, + } : false; return { google, gptPlugins }; diff --git a/api/server/services/Endpoints/google/initialize.js b/api/server/services/Endpoints/google/initialize.js index 60e874d5b8..169d625e3f 100644 --- a/api/server/services/Endpoints/google/initialize.js +++ b/api/server/services/Endpoints/google/initialize.js @@ -1,3 +1,5 @@ +const fs = require('fs'); +const path = require('path'); const { getGoogleConfig, isEnabled } = require('@librechat/api'); const { EModelEndpoint, AuthKeys } = require('librechat-data-provider'); const { getUserKey, checkUserKeyExpiry } = require('~/server/services/UserService'); @@ -15,8 +17,20 @@ const initializeClient = async ({ req, res, endpointOption, overrideModel, optio } let serviceKey = {}; + try { - serviceKey = require('~/data/auth.json'); + if (process.env.GOOGLE_SERVICE_KEY_FILE_PATH) { + const serviceKeyPath = + process.env.GOOGLE_SERVICE_KEY_FILE_PATH || + path.join(__dirname, '../../../../..', 'data', 'auth.json'); + const absolutePath = path.isAbsolute(serviceKeyPath) + ? serviceKeyPath + : path.resolve(serviceKeyPath); + const fileContent = fs.readFileSync(absolutePath, 'utf8'); + serviceKey = JSON.parse(fileContent); + } else { + serviceKey = require('~/data/auth.json'); + } } catch (_e) { // Do nothing } diff --git a/packages/api/src/files/mistral/crud.ts b/packages/api/src/files/mistral/crud.ts index f3ad74b731..5b0d10659a 100644 --- a/packages/api/src/files/mistral/crud.ts +++ b/packages/api/src/files/mistral/crud.ts @@ -439,15 +439,20 @@ async function loadGoogleAuthConfig(): Promise<{ serviceAccount: GoogleServiceAccount; accessToken: string; }> { - /** Path from current file to project root auth.json */ - const authJsonPath = path.join(__dirname, '..', '..', '..', 'api', 'data', 'auth.json'); + /** Path from environment variable or default location */ + const serviceKeyPath = + process.env.GOOGLE_SERVICE_KEY_FILE_PATH || + path.join(__dirname, '..', '..', '..', 'api', 'data', 'auth.json'); + const absolutePath = path.isAbsolute(serviceKeyPath) + ? serviceKeyPath + : path.resolve(serviceKeyPath); let serviceKey: GoogleServiceAccount; try { - const authJsonContent = fs.readFileSync(authJsonPath, 'utf8'); + const authJsonContent = fs.readFileSync(absolutePath, 'utf8'); serviceKey = JSON.parse(authJsonContent) as GoogleServiceAccount; } catch { - throw new Error(`Google service account not found at ${authJsonPath}`); + throw new Error(`Google service account not found at ${absolutePath}`); } if (!serviceKey.client_email || !serviceKey.private_key || !serviceKey.project_id) {