🛟 refactor: Gracefully Skip Unavailable Web Search Rerankers (#13191)
Some checks failed
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Has been cancelled
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Has been cancelled
GitNexus Index / index (push) Has been cancelled
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Has been cancelled
GitNexus Index / post-index (push) Has been cancelled
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Has been cancelled

This commit is contained in:
Danny Avila 2026-05-19 09:48:12 -04:00 committed by GitHub
parent 909329a7e8
commit 2414e9c7d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 11 deletions

View file

@ -689,8 +689,7 @@ describe('web.ts', () => {
const originalEnv = process.env;
process.env = {
...originalEnv,
SERPER_API_KEY: 'test-key',
// Missing other keys to force authentication failure
JINA_API_KEY: 'test-key',
};
// Initialize webSearchConfig with environment variable references
@ -710,10 +709,9 @@ describe('web.ts', () => {
mockLoadAuthValues.mockImplementation(({ authFields }) => {
const result: Record<string, string> = {};
authFields.forEach((field: string) => {
if (field === 'SERPER_API_KEY') {
if (field === 'JINA_API_KEY') {
result[field] = 'test-key';
}
// Other fields are intentionally missing
});
return Promise.resolve(result);
});
@ -1106,6 +1104,47 @@ describe('web.ts', () => {
expect(cohereCalls.length).toBe(0);
});
it('should fallback to no reranker when rerankerType is omitted and no reranker is authenticated', async () => {
const webSearchConfig: TCustomConfig['webSearch'] = {
searxngInstanceUrl: '${SEARXNG_INSTANCE_URL}',
searxngApiKey: '${SEARXNG_API_KEY}',
firecrawlApiKey: '${FIRECRAWL_API_KEY}',
firecrawlApiUrl: '${FIRECRAWL_API_URL}',
jinaApiKey: '${JINA_API_KEY}',
jinaApiUrl: '${JINA_API_URL}',
cohereApiKey: '${COHERE_API_KEY}',
safeSearch: SafeSearchTypes.MODERATE,
searchProvider: 'searxng' as SearchProviders,
scraperProvider: 'firecrawl' as ScraperProviders,
};
mockLoadAuthValues.mockImplementation(({ authFields }) => {
const result: Record<string, string> = {};
authFields.forEach((field: string) => {
if (field === 'SEARXNG_INSTANCE_URL') {
result[field] = 'https://search.example';
} else if (field === 'SEARXNG_API_KEY') {
result[field] = 'searxng-api-key';
} else if (field === 'FIRECRAWL_API_KEY') {
result[field] = 'firecrawl-api-key';
} else if (field === 'FIRECRAWL_API_URL') {
result[field] = 'https://api.firecrawl.dev';
}
});
return Promise.resolve(result);
});
const result = await loadWebSearchAuth({
userId,
webSearchConfig,
loadAuthValues: mockLoadAuthValues,
});
expect(result.authenticated).toBe(true);
expect(result.authResult.rerankerType).toBe('none');
expect(result.authTypes).toContainEqual(['rerankers', AuthType.SYSTEM_DEFINED]);
});
it('should handle invalid specified service gracefully', async () => {
// Initialize a webSearchConfig with an invalid searchProvider
const webSearchConfig: TCustomConfig['webSearch'] = {

View file

@ -7,11 +7,7 @@ import {
extractVariableName,
} from 'librechat-data-provider';
import { webSearchAuth } from '@librechat/data-schemas';
import type {
RerankerTypes,
TCustomConfig,
TWebSearchConfig,
} from 'librechat-data-provider';
import type { RerankerTypes, TCustomConfig, TWebSearchConfig } from 'librechat-data-provider';
import type { TWebSearchKeys, TWebSearchCategories } from '@librechat/data-schemas';
import { isSSRFTarget, resolveHostnameSSRF } from '../auth';
@ -209,8 +205,7 @@ export async function loadWebSearchAuth({
const isUserProvidedOptInUrlKey =
originalKey != null && USER_PROVIDED_OPT_IN_URL_KEYS.has(originalKey);
const isUserProvidedUrlEnabled =
isUserProvidedUrlKey ||
(isUserProvidedOptInUrlKey && isUserProvidedEnabled(field));
isUserProvidedUrlKey || (isUserProvidedOptInUrlKey && isUserProvidedEnabled(field));
let contributed = false;
if (isUserProvidedOptInUrlKey && isFieldUserProvided && !isUserProvidedUrlEnabled) {
@ -253,6 +248,10 @@ export async function loadWebSearchAuth({
continue;
}
}
if (category === SearchCategories.RERANKERS && !webSearchConfig?.rerankerType) {
authResult.rerankerType = 'none' as RerankerTypes;
return [true, false];
}
return [false, isUserProvided];
}