mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-11 12:04:24 +01:00
fix: resolve agent selection race condition in marketplace HandleStartChat
- Set agent in localStorage before newConversation to prevent useSelectorEffects from auto-selecting previous agent
This commit is contained in:
parent
e049fb8821
commit
60db466298
3 changed files with 49 additions and 43 deletions
|
|
@ -1,8 +1,20 @@
|
|||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import type t from 'librechat-data-provider';
|
||||
import { AgentListResponse, PERMISSION_BITS, QueryKeys } from 'librechat-data-provider';
|
||||
import {
|
||||
AgentListResponse,
|
||||
PERMISSION_BITS,
|
||||
QueryKeys,
|
||||
Constants,
|
||||
EModelEndpoint,
|
||||
LocalStorageKeys,
|
||||
} from 'librechat-data-provider';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import { Dialog, DialogContent, Button } from '~/components/ui';
|
||||
import { renderAgentAvatar } from '~/utils/agents';
|
||||
import { DotsIcon } from '~/components/svg';
|
||||
import { useToast, useLocalize } from '~/hooks';
|
||||
|
||||
interface SupportContact {
|
||||
name?: string;
|
||||
email?: string;
|
||||
|
|
@ -11,14 +23,6 @@ interface SupportContact {
|
|||
interface AgentWithSupport extends t.Agent {
|
||||
support_contact?: SupportContact;
|
||||
}
|
||||
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { Dialog, DialogContent, Button } from '~/components/ui';
|
||||
import { renderAgentAvatar } from '~/utils/agents';
|
||||
import useLocalize from '~/hooks/useLocalize';
|
||||
import { DotsIcon } from '~/components/svg';
|
||||
import { useToast } from '~/hooks';
|
||||
|
||||
interface AgentDetailProps {
|
||||
agent: AgentWithSupport; // The agent data to display
|
||||
isOpen: boolean; // Whether the detail dialog is open
|
||||
|
|
@ -30,7 +34,8 @@ interface AgentDetailProps {
|
|||
*/
|
||||
const AgentDetail: React.FC<AgentDetailProps> = ({ agent, isOpen, onClose }) => {
|
||||
const localize = useLocalize();
|
||||
const navigate = useNavigate();
|
||||
// const navigate = useNavigate();
|
||||
const { conversation, newConversation } = useChatContext();
|
||||
const { showToast } = useToast();
|
||||
const dialogRef = useRef<HTMLDivElement>(null);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -67,7 +72,23 @@ const AgentDetail: React.FC<AgentDetailProps> = ({ agent, isOpen, onClose }) =>
|
|||
queryClient.setQueryData<AgentListResponse>(keys, { ...listResp, data: currentAgents });
|
||||
}
|
||||
}
|
||||
navigate(`/c/new?agent_id=${agent.id}`);
|
||||
|
||||
localStorage.setItem(`${LocalStorageKeys.AGENT_ID_PREFIX}0`, agent.id);
|
||||
|
||||
queryClient.setQueryData<t.TMessage[]>(
|
||||
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
||||
[],
|
||||
);
|
||||
queryClient.invalidateQueries([QueryKeys.messages]);
|
||||
|
||||
newConversation({
|
||||
template: {
|
||||
conversationId: Constants.NEW_CONVO as string,
|
||||
endpoint: EModelEndpoint.agents,
|
||||
agent_id: agent.id,
|
||||
title: `Chat with ${agent.name || 'Agent'}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import { useSetRecoilState, useRecoilValue } from 'recoil';
|
||||
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { PermissionTypes, Permissions, QueryKeys, Constants } from 'librechat-data-provider';
|
||||
import { useSearchParams, useParams, useNavigate } from 'react-router-dom';
|
||||
import type t from 'librechat-data-provider';
|
||||
import type { ContextType } from '~/common';
|
||||
|
|
@ -11,7 +12,7 @@ import { useDocumentTitle, useHasAccess } from '~/hooks';
|
|||
import { TooltipAnchor, Button } from '~/components/ui';
|
||||
import { SidePanelGroup } from '~/components/SidePanel';
|
||||
import { OpenSidebar } from '~/components/Chat/Menus';
|
||||
import { SidePanelProvider } from '~/Providers';
|
||||
import { SidePanelProvider, useChatContext } from '~/Providers';
|
||||
import { NewChatIcon } from '~/components/svg';
|
||||
import useLocalize from '~/hooks/useLocalize';
|
||||
import CategoryTabs from './CategoryTabs';
|
||||
|
|
@ -34,6 +35,8 @@ interface AgentMarketplaceProps {
|
|||
const AgentMarketplace: React.FC<AgentMarketplaceProps> = ({ className = '' }) => {
|
||||
const localize = useLocalize();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const { conversation, newConversation } = useChatContext();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const { category } = useParams();
|
||||
const setHideSidePanel = useSetRecoilState(store.hideSidePanel);
|
||||
|
|
@ -142,12 +145,18 @@ const AgentMarketplace: React.FC<AgentMarketplaceProps> = ({ className = '' }) =
|
|||
/**
|
||||
* Handle new chat button click
|
||||
*/
|
||||
|
||||
const handleNewChat = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
if (e.button === 0 && (e.ctrlKey || e.metaKey)) {
|
||||
window.open('/c/new', '_blank');
|
||||
return;
|
||||
}
|
||||
navigate('/c/new');
|
||||
queryClient.setQueryData<t.TMessage[]>(
|
||||
[QueryKeys.messages, conversation?.conversationId ?? Constants.NEW_CONVO],
|
||||
[],
|
||||
);
|
||||
queryClient.invalidateQueries([QueryKeys.messages]);
|
||||
newConversation();
|
||||
};
|
||||
|
||||
// Check if a detail view should be open based on URL
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import React, { useMemo } from 'react';
|
|||
import { EModelEndpoint } from 'librechat-data-provider';
|
||||
|
||||
import { ChatContext } from '~/Providers';
|
||||
import { useChatHelpers } from '~/hooks';
|
||||
|
||||
/**
|
||||
* Minimal marketplace provider that provides only what SidePanel actually needs
|
||||
|
|
@ -13,32 +14,7 @@ interface MarketplaceProviderProps {
|
|||
}
|
||||
|
||||
export const MarketplaceProvider: React.FC<MarketplaceProviderProps> = ({ children }) => {
|
||||
// Create more complete context to prevent FileRow and other component errors
|
||||
// when agents with files are opened in the marketplace
|
||||
const marketplaceContext = useMemo(
|
||||
() => ({
|
||||
conversation: {
|
||||
endpoint: EModelEndpoint.agents,
|
||||
conversationId: 'marketplace',
|
||||
title: 'Agent Marketplace',
|
||||
},
|
||||
// File-related context properties to prevent FileRow errors
|
||||
files: new Map(),
|
||||
setFiles: () => {},
|
||||
setFilesLoading: () => {},
|
||||
// Other commonly used context properties to prevent undefined errors
|
||||
isSubmitting: false,
|
||||
setIsSubmitting: () => {},
|
||||
latestMessage: null,
|
||||
setLatestMessage: () => {},
|
||||
// Minimal functions to prevent errors when components try to use them
|
||||
ask: () => {},
|
||||
regenerate: () => {},
|
||||
stopGenerating: () => {},
|
||||
submitMessage: () => {},
|
||||
}),
|
||||
[],
|
||||
);
|
||||
const chatHelpers = useChatHelpers(0, 'new');
|
||||
|
||||
return <ChatContext.Provider value={marketplaceContext as any}>{children}</ChatContext.Provider>;
|
||||
return <ChatContext.Provider value={chatHelpers as any}>{children}</ChatContext.Provider>;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue