🛜 refactor: Streamline App Config Usage (#9234)

* WIP: app.locals refactoring

WIP: appConfig

fix: update memory configuration retrieval to use getAppConfig based on user role

fix: update comment for AppConfig interface to clarify purpose

🏷️ refactor: Update tests to use getAppConfig for endpoint configurations

ci: Update AppService tests to initialize app config instead of app.locals

ci: Integrate getAppConfig into remaining tests

refactor: Update multer storage destination to use promise-based getAppConfig and improve error handling in tests

refactor: Rename initializeAppConfig to setAppConfig and update related tests

ci: Mock getAppConfig in various tests to provide default configurations

refactor: Update convertMCPToolsToPlugins to use mcpManager for server configuration and adjust related tests

chore: rename `Config/getAppConfig` -> `Config/app`

fix: streamline OpenAI image tools configuration by removing direct appConfig dependency and using function parameters

chore: correct parameter documentation for imageOutputType in ToolService.js

refactor: remove `getCustomConfig` dependency in config route

refactor: update domain validation to use appConfig for allowed domains

refactor: use appConfig registration property

chore: remove app parameter from AppService invocation

refactor: update AppConfig interface to correct registration and turnstile configurations

refactor: remove getCustomConfig dependency and use getAppConfig in PluginController, multer, and MCP services

refactor: replace getCustomConfig with getAppConfig in STTService, TTSService, and related files

refactor: replace getCustomConfig with getAppConfig in Conversation and Message models, update tempChatRetention functions to use AppConfig type

refactor: update getAppConfig calls in Conversation and Message models to include user role for temporary chat expiration

ci: update related tests

refactor: update getAppConfig call in getCustomConfigSpeech to include user role

fix: update appConfig usage to access allowedDomains from actions instead of registration

refactor: enhance AppConfig to include fileStrategies and update related file strategy logic

refactor: update imports to use normalizeEndpointName from @librechat/api and remove redundant definitions

chore: remove deprecated unused RunManager

refactor: get balance config primarily from appConfig

refactor: remove customConfig dependency for appConfig and streamline loadConfigModels logic

refactor: remove getCustomConfig usage and use app config in file citations

refactor: consolidate endpoint loading logic into loadEndpoints function

refactor: update appConfig access to use endpoints structure across various services

refactor: implement custom endpoints configuration and streamline endpoint loading logic

refactor: update getAppConfig call to include user role parameter

refactor: streamline endpoint configuration and enhance appConfig usage across services

refactor: replace getMCPAuthMap with getUserMCPAuthMap and remove unused getCustomConfig file

refactor: add type annotation for loadedEndpoints in loadEndpoints function

refactor: move /services/Files/images/parse to TS API

chore: add missing FILE_CITATIONS permission to IRole interface

refactor: restructure toolkits to TS API

refactor: separate manifest logic into its own module

refactor: consolidate tool loading logic into a new tools module for startup logic

refactor: move interface config logic to TS API

refactor: migrate checkEmailConfig to TypeScript and update imports

refactor: add FunctionTool interface and availableTools to AppConfig

refactor: decouple caching and DB operations from AppService, make part of consolidated `getAppConfig`

WIP: fix tests

* fix: rebase conflicts

* refactor: remove app.locals references

* refactor: replace getBalanceConfig with getAppConfig in various strategies and middleware

* refactor: replace appConfig?.balance with getBalanceConfig in various controllers and clients

* test: add balance configuration to titleConvo method in AgentClient tests

* chore: remove unused `openai-chat-tokens` package

* chore: remove unused imports in initializeMCPs.js

* refactor: update balance configuration to use getAppConfig instead of getBalanceConfig

* refactor: integrate configMiddleware for centralized configuration handling

* refactor: optimize email domain validation by removing unnecessary async calls

* refactor: simplify multer storage configuration by removing async calls

* refactor: reorder imports for better readability in user.js

* refactor: replace getAppConfig calls with req.config for improved performance

* chore: replace getAppConfig calls with req.config in tests for centralized configuration handling

* chore: remove unused override config

* refactor: add configMiddleware to endpoint route and replace getAppConfig with req.config

* chore: remove customConfig parameter from TTSService constructor

* refactor: pass appConfig from request to processFileCitations for improved configuration handling

* refactor: remove configMiddleware from endpoint route and retrieve appConfig directly in getEndpointsConfig if not in `req.config`

* test: add mockAppConfig to processFileCitations tests for improved configuration handling

* fix: pass req.config to hasCustomUserVars and call without await after synchronous refactor

* fix: type safety in useExportConversation

* refactor: retrieve appConfig using getAppConfig in PluginController and remove configMiddleware from plugins route, to avoid always retrieving when plugins are cached

* chore: change `MongoUser` typedef to `IUser`

* fix: Add `user` and `config` fields to ServerRequest and update JSDoc type annotations from Express.Request to ServerRequest

* fix: remove unused setAppConfig mock from Server configuration tests
This commit is contained in:
Danny Avila 2025-08-26 12:10:18 -04:00 committed by GitHub
parent e1ad235f17
commit 9a210971f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
210 changed files with 4102 additions and 3465 deletions

View file

@ -1,45 +0,0 @@
import { useSetRecoilState } from 'recoil';
import { useEffect, useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import type { TEndpointsConfig, TModelsConfig } from 'librechat-data-provider';
import { useGetEndpointsConfigOverride } from '~/data-provider';
import { QueryKeys } from 'librechat-data-provider';
import store from '~/store';
type TempOverrideType = Record<string, unknown> & {
endpointsConfig: TEndpointsConfig;
modelsConfig?: TModelsConfig;
combinedOptions: unknown[];
combined: boolean;
};
export default function useConfigOverride() {
const setEndpointsQueryEnabled = useSetRecoilState(store.endpointsQueryEnabled);
const overrideQuery = useGetEndpointsConfigOverride({
staleTime: Infinity,
});
const queryClient = useQueryClient();
const handleOverride = useCallback(
async (data: unknown | boolean) => {
const { endpointsConfig, modelsConfig } = data as TempOverrideType;
if (endpointsConfig) {
setEndpointsQueryEnabled(false);
await queryClient.cancelQueries([QueryKeys.endpoints]);
queryClient.setQueryData([QueryKeys.endpoints], endpointsConfig);
}
if (modelsConfig) {
await queryClient.cancelQueries([QueryKeys.models]);
queryClient.setQueryData([QueryKeys.models], modelsConfig);
}
},
[queryClient, setEndpointsQueryEnabled],
);
useEffect(() => {
if (overrideQuery.data != null) {
handleOverride(overrideQuery.data);
}
}, [overrideQuery.data, handleOverride]);
}

View file

@ -1,5 +1,6 @@
import download from 'downloadjs';
import { useCallback } from 'react';
import { useParams } from 'react-router-dom';
import exportFromJSON from 'export-from-json';
import { useQueryClient } from '@tanstack/react-query';
import {
@ -10,15 +11,14 @@ import {
isImageVisionTool,
} from 'librechat-data-provider';
import type {
TMessageContentParts,
TConversation,
TMessage,
TPreset,
TConversation,
TMessageContentParts,
} from 'librechat-data-provider';
import useBuildMessageTree from '~/hooks/Messages/useBuildMessageTree';
import { useScreenshot } from '~/hooks/ScreenshotContext';
import { cleanupPreset, buildTree } from '~/utils';
import { useParams } from 'react-router-dom';
type ExportValues = {
fieldName: string;
@ -48,13 +48,14 @@ export default function useExportConversation({
const { conversationId: paramId } = useParams();
const getMessageTree = useCallback(() => {
const queryParam = paramId === 'new' ? paramId : conversation?.conversationId ?? paramId ?? '';
const queryParam =
paramId === 'new' ? paramId : (conversation?.conversationId ?? paramId ?? '');
const messages = queryClient.getQueryData<TMessage[]>([QueryKeys.messages, queryParam]) ?? [];
const dataTree = buildTree({ messages });
return dataTree?.length === 0 ? null : dataTree ?? null;
return dataTree?.length === 0 ? null : (dataTree ?? null);
}, [paramId, conversation?.conversationId, queryClient]);
const getMessageText = (message: TMessage | undefined, format = 'text') => {
const getMessageText = (message: Partial<TMessage> | undefined, format = 'text') => {
if (!message) {
return '';
}
@ -67,7 +68,7 @@ export default function useExportConversation({
};
if (!message.content) {
return formatText(message.sender || '', message.text);
return formatText(message.sender || '', message.text || '');
}
return message.content
@ -90,7 +91,12 @@ export default function useExportConversation({
if (content.type === ContentTypes.ERROR) {
// ERROR
return [sender, content[ContentTypes.TEXT].value];
return [
sender,
typeof content[ContentTypes.TEXT] === 'object'
? (content[ContentTypes.TEXT].value ?? '')
: (content[ContentTypes.TEXT] ?? ''),
];
}
if (content.type === ContentTypes.TEXT) {
@ -156,7 +162,7 @@ export default function useExportConversation({
};
const exportCSV = async () => {
const data: TMessage[] = [];
const data: Partial<TMessage>[] = [];
const messages = await buildMessageTree({
messageId: conversation?.conversationId,
@ -168,6 +174,9 @@ export default function useExportConversation({
if (Array.isArray(messages)) {
for (const message of messages) {
if (!message) {
continue;
}
data.push(message);
}
} else {
@ -245,10 +254,10 @@ export default function useExportConversation({
if (Array.isArray(messages)) {
for (const message of messages) {
data += `${getMessageText(message, 'md')}\n`;
if (message.error) {
if (message?.error) {
data += '*(This is an error message)*\n';
}
if (message.unfinished === true) {
if (message?.unfinished === true) {
data += '*(This is an unfinished message)*\n';
}
data += '\n\n';
@ -301,10 +310,10 @@ export default function useExportConversation({
if (Array.isArray(messages)) {
for (const message of messages) {
data += `${getMessageText(message)}\n`;
if (message.error) {
if (message?.error) {
data += '(This is an error message)\n';
}
if (message.unfinished === true) {
if (message?.unfinished === true) {
data += '(This is an unfinished message)\n';
}
data += '\n\n';