🚀 feat: Use Model Specs + Specific Endpoints, Limit Providers for Agents (#6650)

* 🔧 refactor: Remove modelSpecs prop from ModelSelector and related components

* fix: Update submission.conversationId references in SSE hooks and data types as was incorrectly typed

* feat: Allow showing specific endpoints alongside model specs via `addedEndpoints` field

* feat: allowed agents providers via `agents.allowedProviders` field

* fix: bump dicebear/sharp dependencies to resolve CVE-2024-12905 and improve avatar gen logic

* fix: rename variable for clarity in loadDefaultInterface function

* fix: add keepAddedConvos option to newConversation calls for modular chat support

* fix: include model information in endpoint selection for improved context

* fix: update data-provider version to 0.7.78 and increment config version to 1.2.4
This commit is contained in:
Danny Avila 2025-04-01 03:50:32 -04:00 committed by GitHub
parent cd7cdaa703
commit 90b8769ef3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 905 additions and 777 deletions

View file

@ -16,7 +16,6 @@ const defaultInterface = getConfigDefaults().interface;
export default function Header() {
const { data: startupConfig } = useGetStartupConfig();
const { navVisible } = useOutletContext<ContextType>();
const modelSpecs = useMemo(() => startupConfig?.modelSpecs?.list ?? [], [startupConfig]);
const interfaceConfig = useMemo(
() => startupConfig?.interface ?? defaultInterface,
[startupConfig],
@ -39,7 +38,7 @@ export default function Header() {
<div className="hide-scrollbar flex w-full items-center justify-between gap-2 overflow-x-auto">
<div className="mx-2 flex items-center gap-2">
{!navVisible && <HeaderNewChat />}
{<ModelSelector startupConfig={startupConfig} modelSpecs={modelSpecs} />}
{<ModelSelector startupConfig={startupConfig} />}
{interfaceConfig.presets === true && interfaceConfig.modelSelect && <PresetsMenu />}
{hasAccessToBookmarks === true && <BookmarkMenu />}
{hasAccessToMultiConvo === true && <AddMultiConvo />}

View file

@ -98,9 +98,9 @@ function ModelSelectorContent() {
);
}
export default function ModelSelector({ startupConfig, modelSpecs }: ModelSelectorProps) {
export default function ModelSelector({ startupConfig }: ModelSelectorProps) {
return (
<ModelSelectorProvider modelSpecs={modelSpecs} startupConfig={startupConfig}>
<ModelSelectorProvider startupConfig={startupConfig}>
<ModelSelectorContent />
</ModelSelectorProvider>
);

View file

@ -44,24 +44,20 @@ export function useModelSelectorContext() {
interface ModelSelectorProviderProps {
children: React.ReactNode;
modelSpecs: t.TModelSpec[];
startupConfig: t.TStartupConfig | undefined;
}
export function ModelSelectorProvider({
children,
modelSpecs,
startupConfig,
}: ModelSelectorProviderProps) {
export function ModelSelectorProvider({ children, startupConfig }: ModelSelectorProviderProps) {
const agentsMap = useAgentsMapContext();
const assistantsMap = useAssistantsMapContext();
const { data: endpointsConfig } = useGetEndpointsQuery();
const { conversation, newConversation } = useChatContext();
const modelSpecs = useMemo(() => startupConfig?.modelSpecs?.list ?? [], [startupConfig]);
const { mappedEndpoints, endpointRequiresUserKey } = useEndpoints({
agentsMap,
assistantsMap,
endpointsConfig,
startupConfig,
endpointsConfig,
});
const { onSelectEndpoint, onSelectSpec } = useSelectMention({
// presets,
@ -146,6 +142,7 @@ export function ModelSelectorProvider({
if (isAgentsEndpoint(endpoint.value)) {
onSelectEndpoint?.(endpoint.value, {
agent_id: model,
model: agentsMap?.[model]?.model ?? '',
});
} else if (isAssistantsEndpoint(endpoint.value)) {
onSelectEndpoint?.(endpoint.value, {
@ -157,7 +154,7 @@ export function ModelSelectorProvider({
}
setSelectedValues({
endpoint: endpoint.value,
model: model,
model,
modelSpec: '',
});
};

View file

@ -1,5 +1,5 @@
// file deepcode ignore HardcodedNonCryptoSecret: No hardcoded secrets
import { ViolationTypes, ErrorTypes } from 'librechat-data-provider';
import { ViolationTypes, ErrorTypes, alternateName } from 'librechat-data-provider';
import type { TOpenAIMessage } from 'librechat-data-provider';
import type { LocalizeFunction } from '~/common';
import { formatJSON, extractJson, isJson } from '~/utils/json';
@ -53,6 +53,11 @@ const errorMessages = {
const { info } = json;
return localize('com_error_input_length', { 0: info });
},
[ErrorTypes.INVALID_AGENT_PROVIDER]: (json: TGenericError, localize: LocalizeFunction) => {
const { info } = json;
const provider = (alternateName[info] as string | undefined) ?? info;
return localize('com_error_invalid_agent_provider', { 0: provider });
},
[ErrorTypes.GOOGLE_ERROR]: (json: TGenericError) => {
const { info } = json;
return info;

View file

@ -1,6 +1,6 @@
import { useState, memo } from 'react';
import { useRecoilState } from 'recoil';
import * as Select from '@ariakit/react/select';
import { Fragment, useState, memo } from 'react';
import { FileText, LogOut } from 'lucide-react';
import { LinkIcon, GearIcon, DropdownMenuSeparator } from '~/components';
import { useGetStartupConfig, useGetUserBalance } from '~/data-provider';
@ -23,7 +23,7 @@ function AccountSettings() {
const [showFiles, setShowFiles] = useRecoilState(store.showFiles);
const avatarSrc = useAvatar(user);
const name = user?.avatar ?? user?.username ?? '';
const avatarSeed = user?.avatar || user?.name || user?.username || '';
return (
<Select.SelectProvider>
@ -34,7 +34,7 @@ function AccountSettings() {
>
<div className="-ml-0.9 -mt-0.8 h-8 w-8 flex-shrink-0">
<div className="relative flex">
{name.length === 0 ? (
{avatarSeed.length === 0 ? (
<div
style={{
backgroundColor: 'rgb(121, 137, 255)',
@ -51,7 +51,7 @@ function AccountSettings() {
<img
className="rounded-full"
src={(user?.avatar ?? '') || avatarSrc}
alt={`${name}'s avatar`}
alt={`${user?.name || user?.username || user?.email || ''}'s avatar`}
/>
)}
</div>

View file

@ -56,18 +56,24 @@ export default function AgentPanel({
const { control, handleSubmit, reset } = methods;
const agent_id = useWatch({ control, name: 'id' });
const allowedProviders = useMemo(
() => new Set(agentsConfig?.allowedProviders),
[agentsConfig?.allowedProviders],
);
const providers = useMemo(
() =>
Object.keys(endpointsConfig ?? {})
.filter(
(key) =>
!isAssistantsEndpoint(key) &&
(allowedProviders.size > 0 ? allowedProviders.has(key) : true) &&
key !== EModelEndpoint.agents &&
key !== EModelEndpoint.chatGPTBrowser &&
key !== EModelEndpoint.gptPlugins,
)
.map((provider) => createProviderOption(provider)),
[endpointsConfig],
[endpointsConfig, allowedProviders],
);
/* Mutations */

View file

@ -12,7 +12,7 @@ import { getEndpointField, cn } from '~/utils';
import { useLocalize } from '~/hooks';
import { Panel } from '~/common';
export default function Parameters({
export default function ModelPanel({
setActivePanel,
providers,
models: modelsData,