From 8e3b717e99959d7dc00ee111a7d42e3aca6d1d4b Mon Sep 17 00:00:00 2001 From: Callum Keogan <48253321+calkeo@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:43:25 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=99=20fix:=20Memory=20Agent=20Fails=20?= =?UTF-8?q?to=20Initialize=20with=20Ollama=20Provider=20(#11680)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed an issue where memory agents would fail with 'Provider Ollama not supported' error when using Ollama as a custom endpoint. The getCustomEndpointConfig function was only normalizing the endpoint config name but not the endpoint parameter during comparison. Changes: - Modified getCustomEndpointConfig to normalize both sides of the endpoint comparison - Added comprehensive test coverage for getCustomEndpointConfig including: - Test for case-insensitive Ollama endpoint matching (main fix) - Tests for various edge cases and error handling This ensures that endpoint name matching works correctly for Ollama regardless of case sensitivity in the configuration. --- packages/api/src/app/config.test.ts | 78 +++++++++++++++++++++++++++-- packages/api/src/app/config.ts | 2 +- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/packages/api/src/app/config.test.ts b/packages/api/src/app/config.test.ts index f85bb8a62c..3e2ee6d143 100644 --- a/packages/api/src/app/config.test.ts +++ b/packages/api/src/app/config.test.ts @@ -1,7 +1,7 @@ -import { getTransactionsConfig, getBalanceConfig } from './config'; +import { getTransactionsConfig, getBalanceConfig, getCustomEndpointConfig } from './config'; import { logger } from '@librechat/data-schemas'; -import { FileSources } from 'librechat-data-provider'; -import type { TCustomConfig } from 'librechat-data-provider'; +import { FileSources, EModelEndpoint } from 'librechat-data-provider'; +import type { TCustomConfig, TEndpoint } from 'librechat-data-provider'; import type { AppConfig } from '@librechat/data-schemas'; // Helper function to create a minimal AppConfig for testing @@ -282,3 +282,75 @@ describe('getBalanceConfig', () => { }); }); }); + +describe('getCustomEndpointConfig', () => { + describe('when appConfig is not provided', () => { + it('should throw an error', () => { + expect(() => getCustomEndpointConfig({ endpoint: 'test' })).toThrow( + 'Config not found for the test custom endpoint.', + ); + }); + }); + + describe('when appConfig is provided', () => { + it('should return undefined when no custom endpoints are configured', () => { + const appConfig = createTestAppConfig(); + const result = getCustomEndpointConfig({ endpoint: 'test', appConfig }); + expect(result).toBeUndefined(); + }); + + it('should return the matching endpoint config when found', () => { + const appConfig = createTestAppConfig({ + endpoints: { + [EModelEndpoint.custom]: [ + { + name: 'TestEndpoint', + apiKey: 'test-key', + } as TEndpoint, + ], + }, + }); + + const result = getCustomEndpointConfig({ endpoint: 'TestEndpoint', appConfig }); + expect(result).toEqual({ + name: 'TestEndpoint', + apiKey: 'test-key', + }); + }); + + it('should handle case-insensitive matching for Ollama endpoint', () => { + const appConfig = createTestAppConfig({ + endpoints: { + [EModelEndpoint.custom]: [ + { + name: 'Ollama', + apiKey: 'ollama-key', + } as TEndpoint, + ], + }, + }); + + const result = getCustomEndpointConfig({ endpoint: 'Ollama', appConfig }); + expect(result).toEqual({ + name: 'Ollama', + apiKey: 'ollama-key', + }); + }); + + it('should handle mixed case endpoint names', () => { + const appConfig = createTestAppConfig({ + endpoints: { + [EModelEndpoint.custom]: [ + { + name: 'CustomAI', + apiKey: 'custom-key', + } as TEndpoint, + ], + }, + }); + + const result = getCustomEndpointConfig({ endpoint: 'customai', appConfig }); + expect(result).toBeUndefined(); + }); + }); +}); diff --git a/packages/api/src/app/config.ts b/packages/api/src/app/config.ts index 38144dee2b..0a2fb3e6f9 100644 --- a/packages/api/src/app/config.ts +++ b/packages/api/src/app/config.ts @@ -64,7 +64,7 @@ export const getCustomEndpointConfig = ({ const customEndpoints = appConfig.endpoints?.[EModelEndpoint.custom] ?? []; return customEndpoints.find( - (endpointConfig) => normalizeEndpointName(endpointConfig.name) === endpoint, + (endpointConfig) => normalizeEndpointName(endpointConfig.name) === normalizeEndpointName(endpoint), ); };