🗂️ feat: Add Optional Group Field to ModelSpecs Configuration (#9996)

* feat: Add group field to modelSpecs for flexible grouping

* resolve lint issues

* fix test

* docs: enhance modelSpecs group field documentation for clarity

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Peter Nancarrow 2025-10-11 06:55:06 -05:00 committed by GitHub
parent f61afc1124
commit e9a85d5c65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 215 additions and 39 deletions

View file

@ -214,6 +214,14 @@ export const bedrockEndpointSchema = baseEndpointSchema.merge(
}),
);
const modelItemSchema = z.union([
z.string(),
z.object({
name: z.string(),
description: z.string().optional(),
}),
]);
export const assistantEndpointSchema = baseEndpointSchema.merge(
z.object({
/* assistants specific */
@ -239,7 +247,7 @@ export const assistantEndpointSchema = baseEndpointSchema.merge(
apiKey: z.string().optional(),
models: z
.object({
default: z.array(z.string()).min(1),
default: z.array(modelItemSchema).min(1),
fetch: z.boolean().optional(),
userIdQuery: z.boolean().optional(),
})
@ -299,7 +307,7 @@ export const endpointSchema = baseEndpointSchema.merge(
apiKey: z.string(),
baseURL: z.string(),
models: z.object({
default: z.array(z.string()).min(1),
default: z.array(modelItemSchema).min(1),
fetch: z.boolean().optional(),
userIdQuery: z.boolean().optional(),
}),
@ -636,6 +644,7 @@ export type TStartupConfig = {
helpAndFaqURL: string;
customFooter?: string;
modelSpecs?: TSpecsConfig;
modelDescriptions?: Record<string, Record<string, string>>;
sharedLinksEnabled: boolean;
publicSharedLinksEnabled: boolean;
analyticsGtmId?: string;

View file

@ -15,6 +15,13 @@ export type TModelSpec = {
order?: number;
default?: boolean;
description?: string;
/**
* Optional group name for organizing specs in the UI selector.
* - If it matches an endpoint name (e.g., "openAI", "groq"), the spec appears nested under that endpoint
* - If it's a custom name (doesn't match any endpoint), it creates a separate collapsible group
* - If omitted, the spec appears as a standalone item at the top level
*/
group?: string;
showIconInMenu?: boolean;
showIconInHeader?: boolean;
iconURL?: string | EModelEndpoint; // Allow using project-included icons
@ -28,6 +35,7 @@ export const tModelSpecSchema = z.object({
order: z.number().optional(),
default: z.boolean().optional(),
description: z.string().optional(),
group: z.string().optional(),
showIconInMenu: z.boolean().optional(),
showIconInHeader: z.boolean().optional(),
iconURL: z.union([z.string(), eModelEndpointSchema]).optional(),