mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-27 21:58:51 +01:00
Merge branch 'main' into feature/entra-id-azure-integration
This commit is contained in:
commit
be58d8e4f0
244 changed files with 6722 additions and 3399 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "librechat-data-provider",
|
||||
"version": "0.8.010",
|
||||
"version": "0.8.020",
|
||||
"description": "data services for librechat apps",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.es.js",
|
||||
|
|
|
|||
|
|
@ -10,44 +10,6 @@ import { extractEnvVariable, envVarRegex } from '../src/utils';
|
|||
import { azureGroupConfigsSchema } from '../src/config';
|
||||
import { errorsToString } from '../src/parsers';
|
||||
|
||||
export const deprecatedAzureVariables = [
|
||||
/* "related to" precedes description text */
|
||||
{ key: 'AZURE_OPENAI_DEFAULT_MODEL', description: 'setting a default model' },
|
||||
{ key: 'AZURE_OPENAI_MODELS', description: 'setting models' },
|
||||
{
|
||||
key: 'AZURE_USE_MODEL_AS_DEPLOYMENT_NAME',
|
||||
description: 'using model names as deployment names',
|
||||
},
|
||||
{ key: 'AZURE_API_KEY', description: 'setting a single Azure API key' },
|
||||
{ key: 'AZURE_OPENAI_API_INSTANCE_NAME', description: 'setting a single Azure instance name' },
|
||||
{
|
||||
key: 'AZURE_OPENAI_API_DEPLOYMENT_NAME',
|
||||
description: 'setting a single Azure deployment name',
|
||||
},
|
||||
{ key: 'AZURE_OPENAI_API_VERSION', description: 'setting a single Azure API version' },
|
||||
{
|
||||
key: 'AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME',
|
||||
description: 'setting a single Azure completions deployment name',
|
||||
},
|
||||
{
|
||||
key: 'AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME',
|
||||
description: 'setting a single Azure embeddings deployment name',
|
||||
},
|
||||
{
|
||||
key: 'PLUGINS_USE_AZURE',
|
||||
description: 'using Azure for Plugins',
|
||||
},
|
||||
];
|
||||
|
||||
export const conflictingAzureVariables = [
|
||||
{
|
||||
key: 'INSTANCE_NAME',
|
||||
},
|
||||
{
|
||||
key: 'DEPLOYMENT_NAME',
|
||||
},
|
||||
];
|
||||
|
||||
export function validateAzureGroups(configs: TAzureGroups): TAzureConfigValidationResult {
|
||||
let isValid = true;
|
||||
const modelNames: string[] = [];
|
||||
|
|
@ -239,13 +201,13 @@ export function mapModelToAzureConfig({
|
|||
const { deploymentName = '', version = '' } =
|
||||
typeof modelDetails === 'object'
|
||||
? {
|
||||
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
|
||||
version: modelDetails.version ?? groupConfig.version,
|
||||
}
|
||||
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
|
||||
version: modelDetails.version ?? groupConfig.version,
|
||||
}
|
||||
: {
|
||||
deploymentName: groupConfig.deploymentName,
|
||||
version: groupConfig.version,
|
||||
};
|
||||
deploymentName: groupConfig.deploymentName,
|
||||
version: groupConfig.version,
|
||||
};
|
||||
|
||||
if (!deploymentName || !version) {
|
||||
throw new Error(
|
||||
|
|
@ -335,13 +297,13 @@ export function mapGroupToAzureConfig({
|
|||
const { deploymentName = '', version = '' } =
|
||||
typeof modelDetails === 'object'
|
||||
? {
|
||||
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
|
||||
version: modelDetails.version ?? groupConfig.version,
|
||||
}
|
||||
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
|
||||
version: modelDetails.version ?? groupConfig.version,
|
||||
}
|
||||
: {
|
||||
deploymentName: groupConfig.deploymentName,
|
||||
version: groupConfig.version,
|
||||
};
|
||||
deploymentName: groupConfig.deploymentName,
|
||||
version: groupConfig.version,
|
||||
};
|
||||
|
||||
if (!deploymentName || !version) {
|
||||
throw new Error(
|
||||
|
|
|
|||
|
|
@ -155,8 +155,10 @@ export type TAzureGroupMap = Record<
|
|||
|
||||
export type TValidatedAzureConfig = {
|
||||
modelNames: string[];
|
||||
modelGroupMap: TAzureModelGroupMap;
|
||||
groupMap: TAzureGroupMap;
|
||||
assistantModels?: string[];
|
||||
assistantGroups?: string[];
|
||||
modelGroupMap: TAzureModelGroupMap;
|
||||
};
|
||||
|
||||
export type TAzureConfigValidationResult = TValidatedAzureConfig & {
|
||||
|
|
@ -648,7 +650,7 @@ export type TStartupConfig = {
|
|||
minPasswordLength?: number;
|
||||
webSearch?: {
|
||||
searchProvider?: SearchProviders;
|
||||
scraperType?: ScraperTypes;
|
||||
scraperProvider?: ScraperProviders;
|
||||
rerankerType?: RerankerTypes;
|
||||
};
|
||||
mcpServers?: Record<
|
||||
|
|
@ -687,7 +689,7 @@ export enum SearchProviders {
|
|||
SEARXNG = 'searxng',
|
||||
}
|
||||
|
||||
export enum ScraperTypes {
|
||||
export enum ScraperProviders {
|
||||
FIRECRAWL = 'firecrawl',
|
||||
SERPER = 'serper',
|
||||
}
|
||||
|
|
@ -709,11 +711,12 @@ export const webSearchSchema = z.object({
|
|||
searxngApiKey: z.string().optional().default('${SEARXNG_API_KEY}'),
|
||||
firecrawlApiKey: z.string().optional().default('${FIRECRAWL_API_KEY}'),
|
||||
firecrawlApiUrl: z.string().optional().default('${FIRECRAWL_API_URL}'),
|
||||
firecrawlVersion: z.string().optional().default('${FIRECRAWL_VERSION}'),
|
||||
jinaApiKey: z.string().optional().default('${JINA_API_KEY}'),
|
||||
jinaApiUrl: z.string().optional().default('${JINA_API_URL}'),
|
||||
cohereApiKey: z.string().optional().default('${COHERE_API_KEY}'),
|
||||
searchProvider: z.nativeEnum(SearchProviders).optional(),
|
||||
scraperType: z.nativeEnum(ScraperTypes).optional(),
|
||||
scraperProvider: z.nativeEnum(ScraperProviders).optional(),
|
||||
rerankerType: z.nativeEnum(RerankerTypes).optional(),
|
||||
scraperTimeout: z.number().optional(),
|
||||
safeSearch: z.nativeEnum(SafeSearchTypes).default(SafeSearchTypes.MODERATE),
|
||||
|
|
@ -752,7 +755,7 @@ export const webSearchSchema = z.object({
|
|||
.optional(),
|
||||
});
|
||||
|
||||
export type TWebSearchConfig = z.infer<typeof webSearchSchema>;
|
||||
export type TWebSearchConfig = DeepPartial<z.infer<typeof webSearchSchema>>;
|
||||
|
||||
export const ocrSchema = z.object({
|
||||
mistralModel: z.string().optional(),
|
||||
|
|
@ -799,7 +802,7 @@ export const memorySchema = z.object({
|
|||
.optional(),
|
||||
});
|
||||
|
||||
export type TMemoryConfig = z.infer<typeof memorySchema>;
|
||||
export type TMemoryConfig = DeepPartial<z.infer<typeof memorySchema>>;
|
||||
|
||||
const customEndpointsSchema = z.array(endpointSchema.partial()).optional();
|
||||
|
||||
|
|
@ -862,9 +865,27 @@ export const configSchema = z.object({
|
|||
.optional(),
|
||||
});
|
||||
|
||||
export const getConfigDefaults = () => getSchemaDefaults(configSchema);
|
||||
/**
|
||||
* Recursively makes all properties of T optional, including nested objects.
|
||||
* Handles arrays, primitives, functions, and Date objects correctly.
|
||||
*/
|
||||
export type DeepPartial<T> = T extends (infer U)[]
|
||||
? DeepPartial<U>[]
|
||||
: T extends ReadonlyArray<infer U>
|
||||
? ReadonlyArray<DeepPartial<U>>
|
||||
: // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
T extends Function
|
||||
? T
|
||||
: T extends Date
|
||||
? T
|
||||
: T extends object
|
||||
? {
|
||||
[P in keyof T]?: DeepPartial<T[P]>;
|
||||
}
|
||||
: T;
|
||||
|
||||
export type TCustomConfig = z.infer<typeof configSchema>;
|
||||
export const getConfigDefaults = () => getSchemaDefaults(configSchema);
|
||||
export type TCustomConfig = DeepPartial<z.infer<typeof configSchema>>;
|
||||
export type TCustomEndpoints = z.infer<typeof customEndpointsSchema>;
|
||||
|
||||
export type TProviderSchema =
|
||||
|
|
@ -930,6 +951,13 @@ export const alternateName = {
|
|||
};
|
||||
|
||||
const sharedOpenAIModels = [
|
||||
'gpt-5',
|
||||
'gpt-5-mini',
|
||||
'gpt-5-nano',
|
||||
'gpt-5-chat-latest',
|
||||
'gpt-4.1',
|
||||
'gpt-4.1-mini',
|
||||
'gpt-4.1-nano',
|
||||
'gpt-4o-mini',
|
||||
'gpt-4o',
|
||||
'gpt-4.5-preview',
|
||||
|
|
@ -952,10 +980,14 @@ const sharedOpenAIModels = [
|
|||
];
|
||||
|
||||
const sharedAnthropicModels = [
|
||||
'claude-sonnet-4-5',
|
||||
'claude-sonnet-4-5-20250929',
|
||||
'claude-opus-4-1',
|
||||
'claude-opus-4-1-20250805',
|
||||
'claude-sonnet-4-20250514',
|
||||
'claude-sonnet-4-latest',
|
||||
'claude-sonnet-4-0',
|
||||
'claude-opus-4-20250514',
|
||||
'claude-opus-4-latest',
|
||||
'claude-opus-4-0',
|
||||
'claude-3-7-sonnet-latest',
|
||||
'claude-3-7-sonnet-20250219',
|
||||
'claude-3-5-haiku-20241022',
|
||||
|
|
@ -1013,18 +1045,13 @@ export const defaultModels = {
|
|||
[EModelEndpoint.assistants]: [...sharedOpenAIModels, 'chatgpt-4o-latest'],
|
||||
[EModelEndpoint.agents]: sharedOpenAIModels, // TODO: Add agent models (agentsModels)
|
||||
[EModelEndpoint.google]: [
|
||||
// Gemini 2.5 Models
|
||||
'gemini-2.5-pro',
|
||||
'gemini-2.5-flash',
|
||||
'gemini-2.5-flash-lite',
|
||||
// Gemini 2.0 Models
|
||||
'gemini-2.0-flash-001',
|
||||
'gemini-2.0-flash-exp',
|
||||
'gemini-2.0-flash-lite',
|
||||
'gemini-2.0-pro-exp-02-05',
|
||||
// Gemini 1.5 Models
|
||||
'gemini-1.5-flash-001',
|
||||
'gemini-1.5-flash-002',
|
||||
'gemini-1.5-pro-001',
|
||||
'gemini-1.5-pro-002',
|
||||
// Gemini 1.0 Models
|
||||
'gemini-1.0-pro-001',
|
||||
],
|
||||
[EModelEndpoint.anthropic]: sharedAnthropicModels,
|
||||
[EModelEndpoint.openAI]: [
|
||||
|
|
@ -1107,6 +1134,7 @@ export const visionModels = [
|
|||
'gemini-exp',
|
||||
'gemini-1.5',
|
||||
'gemini-2',
|
||||
'gemini-2.5',
|
||||
'gemini-3',
|
||||
'moondream',
|
||||
'llama3.2-vision',
|
||||
|
|
@ -1530,9 +1558,9 @@ export enum TTSProviders {
|
|||
/** Enum for app-wide constants */
|
||||
export enum Constants {
|
||||
/** Key for the app's version. */
|
||||
VERSION = 'v0.8.0-rc4',
|
||||
VERSION = 'v0.8.0',
|
||||
/** Key for the Custom Config's version (librechat.yaml). */
|
||||
CONFIG_VERSION = '1.2.9',
|
||||
CONFIG_VERSION = '1.3.0',
|
||||
/** Standard value for the first message's `parentMessageId` value, to indicate no parent exists. */
|
||||
NO_PARENT = '00000000-0000-0000-0000-000000000000',
|
||||
/** Standard value to use whatever the submission prelim. `responseMessageId` is */
|
||||
|
|
|
|||
|
|
@ -57,6 +57,27 @@ export const fullMimeTypesList = [
|
|||
'application/zip',
|
||||
'image/svg',
|
||||
'image/svg+xml',
|
||||
// Video formats
|
||||
'video/mp4',
|
||||
'video/avi',
|
||||
'video/mov',
|
||||
'video/wmv',
|
||||
'video/flv',
|
||||
'video/webm',
|
||||
'video/mkv',
|
||||
'video/m4v',
|
||||
'video/3gp',
|
||||
'video/ogv',
|
||||
// Audio formats
|
||||
'audio/mp3',
|
||||
'audio/wav',
|
||||
'audio/ogg',
|
||||
'audio/m4a',
|
||||
'audio/aac',
|
||||
'audio/flac',
|
||||
'audio/wma',
|
||||
'audio/opus',
|
||||
'audio/mpeg',
|
||||
...excelFileTypes,
|
||||
];
|
||||
|
||||
|
|
@ -115,7 +136,7 @@ export const excelMimeTypes =
|
|||
/^application\/(vnd\.ms-excel|msexcel|x-msexcel|x-ms-excel|x-excel|x-dos_ms_excel|xls|x-xls|vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet)$/;
|
||||
|
||||
export const textMimeTypes =
|
||||
/^(text\/(x-c|x-csharp|tab-separated-values|x-c\+\+|x-h|x-java|html|markdown|x-php|x-python|x-script\.python|x-ruby|x-tex|plain|css|vtt|javascript|csv))$/;
|
||||
/^(text\/(x-c|x-csharp|tab-separated-values|x-c\+\+|x-h|x-java|html|markdown|x-php|x-python|x-script\.python|x-ruby|x-tex|plain|css|vtt|javascript|csv|xml))$/;
|
||||
|
||||
export const applicationMimeTypes =
|
||||
/^(application\/(epub\+zip|csv|json|pdf|x-tar|typescript|vnd\.openxmlformats-officedocument\.(wordprocessingml\.document|presentationml\.presentation|spreadsheetml\.sheet)|xml|zip))$/;
|
||||
|
|
@ -123,7 +144,9 @@ export const applicationMimeTypes =
|
|||
export const imageMimeTypes = /^image\/(jpeg|gif|png|webp|heic|heif)$/;
|
||||
|
||||
export const audioMimeTypes =
|
||||
/^audio\/(mp3|mpeg|mpeg3|wav|wave|x-wav|ogg|vorbis|mp4|x-m4a|flac|x-flac|webm)$/;
|
||||
/^audio\/(mp3|mpeg|mpeg3|wav|wave|x-wav|ogg|vorbis|mp4|m4a|x-m4a|flac|x-flac|webm|aac|wma|opus)$/;
|
||||
|
||||
export const videoMimeTypes = /^video\/(mp4|avi|mov|wmv|flv|webm|mkv|m4v|3gp|ogv)$/;
|
||||
|
||||
export const defaultOCRMimeTypes = [
|
||||
imageMimeTypes,
|
||||
|
|
@ -142,8 +165,9 @@ export const supportedMimeTypes = [
|
|||
excelMimeTypes,
|
||||
applicationMimeTypes,
|
||||
imageMimeTypes,
|
||||
videoMimeTypes,
|
||||
audioMimeTypes,
|
||||
/** Supported by LC Code Interpreter PAI */
|
||||
/** Supported by LC Code Interpreter API */
|
||||
/^image\/(svg|svg\+xml)$/,
|
||||
];
|
||||
|
||||
|
|
@ -199,6 +223,13 @@ export const fileConfig = {
|
|||
[EModelEndpoint.assistants]: assistantsFileConfig,
|
||||
[EModelEndpoint.azureAssistants]: assistantsFileConfig,
|
||||
[EModelEndpoint.agents]: assistantsFileConfig,
|
||||
[EModelEndpoint.anthropic]: {
|
||||
fileLimit: 10,
|
||||
fileSizeLimit: defaultSizeLimit,
|
||||
totalSizeLimit: defaultSizeLimit,
|
||||
supportedMimeTypes,
|
||||
disabled: false,
|
||||
},
|
||||
default: {
|
||||
fileLimit: 10,
|
||||
fileSizeLimit: defaultSizeLimit,
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ export function parseTextParts(
|
|||
continue;
|
||||
}
|
||||
if (part.type === ContentTypes.TEXT) {
|
||||
const textValue = typeof part.text === 'string' ? part.text : part.text.value;
|
||||
const textValue = (typeof part.text === 'string' ? part.text : part.text?.value) || '';
|
||||
|
||||
if (
|
||||
result.length > 0 &&
|
||||
|
|
|
|||
|
|
@ -31,6 +31,61 @@ export enum EModelEndpoint {
|
|||
gptPlugins = 'gptPlugins',
|
||||
}
|
||||
|
||||
/** Mirrors `@librechat/agents` providers */
|
||||
export enum Providers {
|
||||
OPENAI = 'openAI',
|
||||
ANTHROPIC = 'anthropic',
|
||||
AZURE = 'azureOpenAI',
|
||||
GOOGLE = 'google',
|
||||
VERTEXAI = 'vertexai',
|
||||
BEDROCK = 'bedrock',
|
||||
BEDROCK_LEGACY = 'bedrock_legacy',
|
||||
MISTRALAI = 'mistralai',
|
||||
MISTRAL = 'mistral',
|
||||
OLLAMA = 'ollama',
|
||||
DEEPSEEK = 'deepseek',
|
||||
OPENROUTER = 'openrouter',
|
||||
XAI = 'xai',
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoints that support direct PDF processing in the agent system
|
||||
*/
|
||||
export const documentSupportedProviders = new Set<string>([
|
||||
EModelEndpoint.anthropic,
|
||||
EModelEndpoint.openAI,
|
||||
EModelEndpoint.custom,
|
||||
EModelEndpoint.azureOpenAI,
|
||||
EModelEndpoint.google,
|
||||
Providers.VERTEXAI,
|
||||
Providers.MISTRALAI,
|
||||
Providers.MISTRAL,
|
||||
Providers.OLLAMA,
|
||||
Providers.DEEPSEEK,
|
||||
Providers.OPENROUTER,
|
||||
Providers.XAI,
|
||||
]);
|
||||
|
||||
const openAILikeProviders = new Set<string>([
|
||||
Providers.OPENAI,
|
||||
Providers.AZURE,
|
||||
EModelEndpoint.custom,
|
||||
Providers.MISTRALAI,
|
||||
Providers.MISTRAL,
|
||||
Providers.OLLAMA,
|
||||
Providers.DEEPSEEK,
|
||||
Providers.OPENROUTER,
|
||||
Providers.XAI,
|
||||
]);
|
||||
|
||||
export const isOpenAILikeProvider = (provider?: string | null): boolean => {
|
||||
return openAILikeProviders.has(provider ?? '');
|
||||
};
|
||||
|
||||
export const isDocumentSupportedProvider = (provider?: string | null): boolean => {
|
||||
return documentSupportedProviders.has(provider ?? '');
|
||||
};
|
||||
|
||||
export const paramEndpoints = new Set<EModelEndpoint | string>([
|
||||
EModelEndpoint.agents,
|
||||
EModelEndpoint.openAI,
|
||||
|
|
|
|||
|
|
@ -475,10 +475,20 @@ export type ContentPart = (
|
|||
) &
|
||||
PartMetadata;
|
||||
|
||||
export type TextData = (Text & PartMetadata) | undefined;
|
||||
|
||||
export type TMessageContentParts =
|
||||
| { type: ContentTypes.ERROR; text?: string | (Text & PartMetadata); error?: string }
|
||||
| { type: ContentTypes.THINK; think: string | (Text & PartMetadata) }
|
||||
| { type: ContentTypes.TEXT; text: string | (Text & PartMetadata); tool_call_ids?: string[] }
|
||||
| {
|
||||
type: ContentTypes.ERROR;
|
||||
text?: string | TextData;
|
||||
error?: string;
|
||||
}
|
||||
| { type: ContentTypes.THINK; think?: string | TextData }
|
||||
| {
|
||||
type: ContentTypes.TEXT;
|
||||
text?: string | TextData;
|
||||
tool_call_ids?: string[];
|
||||
}
|
||||
| {
|
||||
type: ContentTypes.TOOL_CALL;
|
||||
tool_call: (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue