mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-04 01:28:51 +01:00
🥷 fix: Correct Agents Handling for Marketplace Users (#9065)
* refactor: Introduce ModelSelectorChatContext and integrate with ModelSelector * fix: agents handling in ModelSelector to show expected agents if user has marketplace access
This commit is contained in:
parent
e4e25aaf2b
commit
d57e7aec73
8 changed files with 124 additions and 57 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { ModelSelectorProps } from '~/common';
|
||||
import { ModelSelectorProvider, useModelSelectorContext } from './ModelSelectorContext';
|
||||
import { ModelSelectorChatProvider } from './ModelSelectorChatContext';
|
||||
import { renderModelSpecs, renderEndpoints, renderSearchResults } from './components';
|
||||
import { getSelectedIcon, getDisplayValue } from './utils';
|
||||
import { CustomMenu as Menu } from './CustomMenu';
|
||||
|
|
@ -12,6 +13,7 @@ function ModelSelectorContent() {
|
|||
|
||||
const {
|
||||
// LibreChat
|
||||
agentsMap,
|
||||
modelSpecs,
|
||||
mappedEndpoints,
|
||||
endpointsConfig,
|
||||
|
|
@ -43,11 +45,12 @@ function ModelSelectorContent() {
|
|||
() =>
|
||||
getDisplayValue({
|
||||
localize,
|
||||
agentsMap,
|
||||
modelSpecs,
|
||||
selectedValues,
|
||||
mappedEndpoints,
|
||||
}),
|
||||
[localize, modelSpecs, selectedValues, mappedEndpoints],
|
||||
[localize, agentsMap, modelSpecs, selectedValues, mappedEndpoints],
|
||||
);
|
||||
|
||||
const trigger = (
|
||||
|
|
@ -100,8 +103,10 @@ function ModelSelectorContent() {
|
|||
|
||||
export default function ModelSelector({ startupConfig }: ModelSelectorProps) {
|
||||
return (
|
||||
<ModelSelectorProvider startupConfig={startupConfig}>
|
||||
<ModelSelectorContent />
|
||||
</ModelSelectorProvider>
|
||||
<ModelSelectorChatProvider>
|
||||
<ModelSelectorProvider startupConfig={startupConfig}>
|
||||
<ModelSelectorContent />
|
||||
</ModelSelectorProvider>
|
||||
</ModelSelectorChatProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
import React, { createContext, useContext, useMemo } from 'react';
|
||||
import type { EModelEndpoint } from 'librechat-data-provider';
|
||||
import { useChatContext } from '~/Providers/ChatContext';
|
||||
|
||||
interface ModelSelectorChatContextValue {
|
||||
endpoint?: EModelEndpoint | null;
|
||||
model?: string | null;
|
||||
spec?: string | null;
|
||||
agent_id?: string | null;
|
||||
assistant_id?: string | null;
|
||||
newConversation: ReturnType<typeof useChatContext>['newConversation'];
|
||||
}
|
||||
|
||||
const ModelSelectorChatContext = createContext<ModelSelectorChatContextValue | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
export function ModelSelectorChatProvider({ children }: { children: React.ReactNode }) {
|
||||
const { conversation, newConversation } = useChatContext();
|
||||
|
||||
/** Context value only created when relevant conversation properties change */
|
||||
const contextValue = useMemo<ModelSelectorChatContextValue>(
|
||||
() => ({
|
||||
endpoint: conversation?.endpoint,
|
||||
model: conversation?.model,
|
||||
spec: conversation?.spec,
|
||||
agent_id: conversation?.agent_id,
|
||||
assistant_id: conversation?.assistant_id,
|
||||
newConversation,
|
||||
}),
|
||||
[
|
||||
conversation?.endpoint,
|
||||
conversation?.model,
|
||||
conversation?.spec,
|
||||
conversation?.agent_id,
|
||||
conversation?.assistant_id,
|
||||
newConversation,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<ModelSelectorChatContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</ModelSelectorChatContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useModelSelectorChatContext() {
|
||||
const context = useContext(ModelSelectorChatContext);
|
||||
if (!context) {
|
||||
throw new Error('useModelSelectorChatContext must be used within ModelSelectorChatProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
|
@ -3,10 +3,16 @@ import React, { createContext, useContext, useState, useMemo } from 'react';
|
|||
import { isAgentsEndpoint, isAssistantsEndpoint } from 'librechat-data-provider';
|
||||
import type * as t from 'librechat-data-provider';
|
||||
import type { Endpoint, SelectedValues } from '~/common';
|
||||
import { useAgentsMapContext, useAssistantsMapContext, useChatContext } from '~/Providers';
|
||||
import { useEndpoints, useSelectorEffects, useKeyDialog } from '~/hooks';
|
||||
import {
|
||||
useAgentDefaultPermissionLevel,
|
||||
useSelectorEffects,
|
||||
useKeyDialog,
|
||||
useEndpoints,
|
||||
} from '~/hooks';
|
||||
import { useAgentsMapContext, useAssistantsMapContext } from '~/Providers';
|
||||
import { useGetEndpointsQuery, useListAgentsQuery } from '~/data-provider';
|
||||
import { useModelSelectorChatContext } from './ModelSelectorChatContext';
|
||||
import useSelectMention from '~/hooks/Input/useSelectMention';
|
||||
import { useGetEndpointsQuery } from '~/data-provider';
|
||||
import { filterItems } from './utils';
|
||||
|
||||
type ModelSelectorContextType = {
|
||||
|
|
@ -51,14 +57,24 @@ export function ModelSelectorProvider({ children, startupConfig }: ModelSelector
|
|||
const agentsMap = useAgentsMapContext();
|
||||
const assistantsMap = useAssistantsMapContext();
|
||||
const { data: endpointsConfig } = useGetEndpointsQuery();
|
||||
const { conversation, newConversation } = useChatContext();
|
||||
const { endpoint, model, spec, agent_id, assistant_id, newConversation } =
|
||||
useModelSelectorChatContext();
|
||||
const modelSpecs = useMemo(() => startupConfig?.modelSpecs?.list ?? [], [startupConfig]);
|
||||
const permissionLevel = useAgentDefaultPermissionLevel();
|
||||
const { data: agents = null } = useListAgentsQuery(
|
||||
{ requiredPermission: permissionLevel },
|
||||
{
|
||||
select: (data) => data?.data,
|
||||
},
|
||||
);
|
||||
|
||||
const { mappedEndpoints, endpointRequiresUserKey } = useEndpoints({
|
||||
agentsMap,
|
||||
agents,
|
||||
assistantsMap,
|
||||
startupConfig,
|
||||
endpointsConfig,
|
||||
});
|
||||
|
||||
const { onSelectEndpoint, onSelectSpec } = useSelectMention({
|
||||
// presets,
|
||||
modelSpecs,
|
||||
|
|
@ -70,13 +86,21 @@ export function ModelSelectorProvider({ children, startupConfig }: ModelSelector
|
|||
|
||||
// State
|
||||
const [selectedValues, setSelectedValues] = useState<SelectedValues>({
|
||||
endpoint: conversation?.endpoint || '',
|
||||
model: conversation?.model || '',
|
||||
modelSpec: conversation?.spec || '',
|
||||
endpoint: endpoint || '',
|
||||
model: model || '',
|
||||
modelSpec: spec || '',
|
||||
});
|
||||
useSelectorEffects({
|
||||
agentsMap,
|
||||
conversation,
|
||||
conversation: endpoint
|
||||
? ({
|
||||
endpoint: endpoint ?? null,
|
||||
model: model ?? null,
|
||||
spec: spec ?? null,
|
||||
agent_id: agent_id ?? null,
|
||||
assistant_id: assistant_id ?? null,
|
||||
} as any)
|
||||
: null,
|
||||
assistantsMap,
|
||||
setSelectedValues,
|
||||
});
|
||||
|
|
@ -86,7 +110,7 @@ export function ModelSelectorProvider({ children, startupConfig }: ModelSelector
|
|||
|
||||
const keyProps = useKeyDialog();
|
||||
|
||||
// Memoized search results
|
||||
/** Memoized search results */
|
||||
const searchResults = useMemo(() => {
|
||||
if (!searchValue) {
|
||||
return null;
|
||||
|
|
@ -95,7 +119,6 @@ export function ModelSelectorProvider({ children, startupConfig }: ModelSelector
|
|||
return filterItems(allItems, searchValue, agentsMap, assistantsMap || {});
|
||||
}, [searchValue, modelSpecs, mappedEndpoints, agentsMap, assistantsMap]);
|
||||
|
||||
// Functions
|
||||
const setDebouncedSearchValue = useMemo(
|
||||
() =>
|
||||
debounce((value: string) => {
|
||||
|
|
|
|||
|
|
@ -167,11 +167,13 @@ export const getDisplayValue = ({
|
|||
mappedEndpoints,
|
||||
selectedValues,
|
||||
modelSpecs,
|
||||
agentsMap,
|
||||
}: {
|
||||
localize: ReturnType<typeof useLocalize>;
|
||||
selectedValues: SelectedValues;
|
||||
mappedEndpoints: Endpoint[];
|
||||
modelSpecs: TModelSpec[];
|
||||
agentsMap?: TAgentsMap;
|
||||
}) => {
|
||||
if (selectedValues.modelSpec) {
|
||||
const spec = modelSpecs.find((s) => s.name === selectedValues.modelSpec);
|
||||
|
|
@ -190,6 +192,9 @@ export const getDisplayValue = ({
|
|||
endpoint.agentNames[selectedValues.model]
|
||||
) {
|
||||
return endpoint.agentNames[selectedValues.model];
|
||||
} else if (isAgentsEndpoint(endpoint.value) && agentsMap) {
|
||||
const agent = agentsMap[selectedValues.model];
|
||||
return agent?.name || selectedValues.model;
|
||||
}
|
||||
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import type { UseMutationResult, QueryObserverResult } from '@tanstack/react-que
|
|||
import type { Agent, AgentCreateParams } from 'librechat-data-provider';
|
||||
import type { TAgentCapabilities, AgentForm } from '~/common';
|
||||
import { cn, createProviderOption, processAgentOption, getDefaultAgentFormValues } from '~/utils';
|
||||
import { useGetStartupConfig, useListAgentsQuery } from '~/data-provider';
|
||||
import { useLocalize, useAgentDefaultPermissionLevel } from '~/hooks';
|
||||
import { useListAgentsQuery } from '~/data-provider';
|
||||
|
||||
const keys = new Set(Object.keys(defaultAgentFormValues));
|
||||
|
||||
|
|
@ -26,8 +26,6 @@ export default function AgentSelect({
|
|||
const localize = useLocalize();
|
||||
const lastSelectedAgent = useRef<string | null>(null);
|
||||
const { control, reset } = useFormContext();
|
||||
|
||||
const { data: startupConfig } = useGetStartupConfig();
|
||||
const permissionLevel = useAgentDefaultPermissionLevel();
|
||||
|
||||
const { data: agents = null } = useListAgentsQuery(
|
||||
|
|
@ -40,7 +38,6 @@ export default function AgentSelect({
|
|||
...agent,
|
||||
name: agent.name || agent.id,
|
||||
},
|
||||
instanceProjectId: startupConfig?.instanceProjectId,
|
||||
}),
|
||||
),
|
||||
},
|
||||
|
|
@ -122,7 +119,7 @@ export default function AgentSelect({
|
|||
|
||||
reset(formValues);
|
||||
},
|
||||
[reset, startupConfig],
|
||||
[reset],
|
||||
);
|
||||
|
||||
const onSelect = useCallback(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue