🐛 fix: Ensure Default ModelSpecs Are Set Correctly (#5218)

* 🐛 fix: default modelSpecs not being set

* feat: Add imageDetail parameter for OpenAI endpoints in tQueryParamsSchema

* feat: Implement processModelSpecs function to enhance model specs processing from configuration

* feat: Refactor configuration schemas and types for improved structure and clarity

* feat: Add append_current_datetime parameter to tQueryParamsSchema for enhanced endpoint functionality

* fix: Add endpointType to getSaveOptions and enhance endpoint handling in Settings component

* fix: Change endpointType to be nullable and optional in tConversationSchema for improved flexibility

* fix: allow save & submit for google endpoint
This commit is contained in:
Danny Avila 2025-01-08 21:57:00 -05:00 committed by GitHub
parent 916faf6447
commit 69a9b8b911
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 201 additions and 148 deletions

View file

@ -1,6 +1,6 @@
{
"name": "librechat-data-provider",
"version": "0.7.691",
"version": "0.7.692",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",

View file

@ -4,7 +4,7 @@ import type { ZodError } from 'zod';
import type { TModelsConfig } from './types';
import { EModelEndpoint, eModelEndpointSchema } from './schemas';
import { fileConfigSchema } from './file-config';
import { specsConfigSchema } from './models';
import { specsConfigSchema, TSpecsConfig } from './models';
import { FileSources } from './types/files';
import { MCPServersSchema } from './mcp';
@ -427,6 +427,82 @@ export enum EImageOutputType {
JPEG = 'jpeg',
}
export const intefaceSchema = z
.object({
privacyPolicy: z
.object({
externalUrl: z.string().optional(),
openNewTab: z.boolean().optional(),
})
.optional(),
termsOfService: z
.object({
externalUrl: z.string().optional(),
openNewTab: z.boolean().optional(),
modalAcceptance: z.boolean().optional(),
modalTitle: z.string().optional(),
modalContent: z.string().or(z.array(z.string())).optional(),
})
.optional(),
endpointsMenu: z.boolean().optional(),
modelSelect: z.boolean().optional(),
parameters: z.boolean().optional(),
sidePanel: z.boolean().optional(),
multiConvo: z.boolean().optional(),
bookmarks: z.boolean().optional(),
presets: z.boolean().optional(),
prompts: z.boolean().optional(),
agents: z.boolean().optional(),
})
.default({
endpointsMenu: true,
modelSelect: true,
parameters: true,
sidePanel: true,
presets: true,
multiConvo: true,
bookmarks: true,
prompts: true,
agents: true,
});
export type TInterfaceConfig = z.infer<typeof intefaceSchema>;
export type TStartupConfig = {
appTitle: string;
socialLogins?: string[];
interface?: TInterfaceConfig;
discordLoginEnabled: boolean;
facebookLoginEnabled: boolean;
githubLoginEnabled: boolean;
googleLoginEnabled: boolean;
openidLoginEnabled: boolean;
openidLabel: string;
openidImageUrl: string;
/** LDAP Auth Configuration */
ldap?: {
/** LDAP enabled */
enabled: boolean;
/** Whether LDAP uses username vs. email */
username?: boolean;
};
serverDomain: string;
emailLoginEnabled: boolean;
registrationEnabled: boolean;
socialLoginEnabled: boolean;
passwordResetEnabled: boolean;
emailEnabled: boolean;
checkBalance: boolean;
showBirthdayIcon: boolean;
helpAndFaqURL: string;
customFooter?: string;
modelSpecs?: TSpecsConfig;
sharedLinksEnabled: boolean;
publicSharedLinksEnabled: boolean;
analyticsGtmId?: string;
instanceProjectId: string;
};
export const configSchema = z.object({
version: z.string(),
cache: z.boolean().default(true),
@ -435,44 +511,7 @@ export const configSchema = z.object({
includedTools: z.array(z.string()).optional(),
filteredTools: z.array(z.string()).optional(),
mcpServers: MCPServersSchema.optional(),
interface: z
.object({
privacyPolicy: z
.object({
externalUrl: z.string().optional(),
openNewTab: z.boolean().optional(),
})
.optional(),
termsOfService: z
.object({
externalUrl: z.string().optional(),
openNewTab: z.boolean().optional(),
modalAcceptance: z.boolean().optional(),
modalTitle: z.string().optional(),
modalContent: z.string().or(z.array(z.string())).optional(),
})
.optional(),
endpointsMenu: z.boolean().optional(),
modelSelect: z.boolean().optional(),
parameters: z.boolean().optional(),
sidePanel: z.boolean().optional(),
multiConvo: z.boolean().optional(),
bookmarks: z.boolean().optional(),
presets: z.boolean().optional(),
prompts: z.boolean().optional(),
agents: z.boolean().optional(),
})
.default({
endpointsMenu: true,
modelSelect: true,
parameters: true,
sidePanel: true,
presets: true,
multiConvo: true,
bookmarks: true,
prompts: true,
agents: true,
}),
interface: intefaceSchema,
fileStrategy: fileSourceSchema.default(FileSources.local),
actions: z
.object({

View file

@ -173,7 +173,7 @@ export const updateUserPlugins = (payload: t.TUpdateUserPlugins) => {
/* Config */
export const getStartupConfig = (): Promise<t.TStartupConfig> => {
export const getStartupConfig = (): Promise<config.TStartupConfig> => {
return request.get(endpoints.config());
};

View file

@ -37,7 +37,7 @@ export const tModelSpecSchema = z.object({
export const specsConfigSchema = z.object({
enforce: z.boolean().default(false),
prioritize: z.boolean().default(true),
list: z.array(tModelSpecSchema).optional(),
list: z.array(tModelSpecSchema).min(1),
});
export type TSpecsConfig = z.infer<typeof specsConfigSchema>;

View file

@ -5,6 +5,7 @@ import type {
QueryObserverResult,
} from '@tanstack/react-query';
import { initialModelsConfig, LocalStorageKeys } from '../config';
import type { TStartupConfig } from '../config';
import { defaultOrderQuery } from '../types/assistants';
import * as dataService from '../data-service';
import * as m from '../types/mutations';
@ -423,18 +424,14 @@ export const useUpdateUserPluginsMutation = (
};
export const useGetStartupConfig = (
config?: UseQueryOptions<t.TStartupConfig>,
): QueryObserverResult<t.TStartupConfig> => {
return useQuery<t.TStartupConfig>(
[QueryKeys.startupConfig],
() => dataService.getStartupConfig(),
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
},
);
config?: UseQueryOptions<TStartupConfig>,
): QueryObserverResult<TStartupConfig> => {
return useQuery<TStartupConfig>([QueryKeys.startupConfig], () => dataService.getStartupConfig(), {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
});
};
export const useGetCustomConfigSpeechQuery = (

View file

@ -526,7 +526,7 @@ const DocumentType: z.ZodType<DocumentTypeValue> = z.lazy(() =>
export const tConversationSchema = z.object({
conversationId: z.string().nullable(),
endpoint: eModelEndpointSchema.nullable(),
endpointType: eModelEndpointSchema.optional(),
endpointType: eModelEndpointSchema.nullable().optional(),
isArchived: z.boolean().optional(),
title: z.string().nullable().or(z.literal('New Chat')).default('New Chat'),
user: z.string().optional(),
@ -559,9 +559,9 @@ export const tConversationSchema = z.object({
createdAt: z.string(),
updatedAt: z.string(),
/* Files */
resendFiles: z.boolean().optional(),
file_ids: z.array(z.string()).optional(),
/* vision */
resendFiles: z.boolean().optional(),
imageDetail: eImageDetailSchema.optional(),
/* assistant */
assistant_id: z.string().optional(),
@ -571,16 +571,17 @@ export const tConversationSchema = z.object({
region: z.string().optional(),
maxTokens: coerceNumber.optional(),
additionalModelRequestFields: DocumentType.optional(),
/* assistant + agents */
/* assistants */
instructions: z.string().optional(),
additional_instructions: z.string().optional(),
append_current_datetime: z.boolean().optional(),
/** Used to overwrite active conversation settings when saving a Preset */
presetOverride: z.record(z.unknown()).optional(),
stop: z.array(z.string()).optional(),
/* frontend components */
iconURL: z.string().optional(),
greeting: z.string().optional(),
spec: z.string().optional(),
spec: z.string().nullable().optional(),
iconURL: z.string().nullable().optional(),
/*
Deprecated fields
*/
@ -606,7 +607,6 @@ export const tConversationSchema = z.object({
agentOptions: tAgentOptionsSchema.nullable().optional(),
/** @deprecated Prefer `modelLabel` over `chatGptLabel` */
chatGptLabel: z.string().nullable().optional(),
append_current_datetime: z.boolean().optional(),
});
export const tPresetSchema = tConversationSchema
@ -642,6 +642,13 @@ export const tQueryParamsSchema = tConversationSchema
* Whether or not to re-submit files from previous messages on subsequent messages
* */
resendFiles: true,
/**
* @endpoints openAI, custom, azureOpenAI
*
* System parameter that only affects the above endpoints.
* Image detail for re-sizing according to OpenAI spec, defaults to `auto`
* */
imageDetail: true,
/**
* AKA Custom Instructions, dynamically added to chat history as a system message;
* for `bedrock` endpoint, this is used as the `system` model param if the provider uses it;
@ -681,6 +688,8 @@ export const tQueryParamsSchema = tConversationSchema
agent_id: true,
/** @endpoints assistants, azureAssistants */
assistant_id: true,
/** @endpoints assistants, azureAssistants */
append_current_datetime: true,
/**
* @endpoints assistants, azureAssistants
*

View file

@ -10,7 +10,6 @@ import type {
TConversationTag,
TBanner,
} from './schemas';
import type { TSpecsConfig } from './models';
export type TOpenAIMessage = OpenAI.Chat.ChatCompletionMessageParam;
export * from './schemas';
@ -108,7 +107,7 @@ export type TUser = {
avatar: string;
role: string;
provider: string;
plugins: string[];
plugins?: string[];
createdAt: string;
updatedAt: string;
};
@ -312,63 +311,6 @@ export type TVerifyEmail = {
export type TResendVerificationEmail = Omit<TVerifyEmail, 'token'>;
export type TInterfaceConfig = {
privacyPolicy?: {
externalUrl?: string;
openNewTab?: boolean;
};
termsOfService?: {
externalUrl?: string;
openNewTab?: boolean;
modalAcceptance?: boolean;
modalTitle?: string;
modalContent?: string;
};
endpointsMenu: boolean;
modelSelect: boolean;
parameters: boolean;
sidePanel: boolean;
presets: boolean;
multiConvo: boolean;
bookmarks: boolean;
prompts: boolean;
};
export type TStartupConfig = {
appTitle: string;
socialLogins?: string[];
interface?: TInterfaceConfig;
discordLoginEnabled: boolean;
facebookLoginEnabled: boolean;
githubLoginEnabled: boolean;
googleLoginEnabled: boolean;
openidLoginEnabled: boolean;
openidLabel: string;
openidImageUrl: string;
/** LDAP Auth Configuration */
ldap?: {
/** LDAP enabled */
enabled: boolean;
/** Whether LDAP uses username vs. email */
username?: boolean;
};
serverDomain: string;
emailLoginEnabled: boolean;
registrationEnabled: boolean;
socialLoginEnabled: boolean;
passwordResetEnabled: boolean;
emailEnabled: boolean;
checkBalance: boolean;
showBirthdayIcon: boolean;
helpAndFaqURL: string;
customFooter?: string;
modelSpecs?: TSpecsConfig;
sharedLinksEnabled: boolean;
publicSharedLinksEnabled: boolean;
analyticsGtmId?: string;
instanceProjectId: string;
};
export type TRefreshTokenResponse = {
token: string;
user: TUser;