From 4d07e90df2c3176c4c48a5a93a2e033a55b8eda2 Mon Sep 17 00:00:00 2001 From: puzhen <1303385763@qq.com> Date: Wed, 22 Oct 2025 12:56:38 +0100 Subject: [PATCH] fix: display bugs --- backend/app/utils/listen/toolkit_listen.py | 18 ++++++++++++------ src/components/ChatBox/TaskCard.tsx | 20 ++++++++++++++++++-- src/components/ChatBox/UserQueryGroup.tsx | 9 +++++---- src/components/TopBar/index.tsx | 8 ++++---- src/pages/Home.tsx | 8 ++++---- src/store/chatStore.ts | 3 ++- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/backend/app/utils/listen/toolkit_listen.py b/backend/app/utils/listen/toolkit_listen.py index fb5b9bf5f..7e98713ba 100644 --- a/backend/app/utils/listen/toolkit_listen.py +++ b/backend/app/utils/listen/toolkit_listen.py @@ -285,11 +285,17 @@ def auto_listen_toolkit(base_toolkit_class: Type[T]) -> Callable[[Type[T]], Type for method_name, base_method in base_methods.items(): if method_name in cls.__dict__: continue - + sig = signature(base_method) - + def create_wrapper(method_name: str, base_method: Callable) -> Callable: - if iscoroutinefunction(base_method): + # Unwrap decorators to check the actual function + unwrapped_method = base_method + while hasattr(unwrapped_method, '__wrapped__'): + unwrapped_method = unwrapped_method.__wrapped__ + + # Check if the unwrapped method is a coroutine function + if iscoroutinefunction(unwrapped_method): async def async_method_wrapper(self, *args, **kwargs): return await getattr(super(cls, self), method_name)(*args, **kwargs) async_method_wrapper.__name__ = method_name @@ -301,12 +307,12 @@ def auto_listen_toolkit(base_toolkit_class: Type[T]) -> Callable[[Type[T]], Type sync_method_wrapper.__name__ = method_name sync_method_wrapper.__signature__ = sig return sync_method_wrapper - + wrapper = create_wrapper(method_name, base_method) decorated_method = listen_toolkit(base_method)(wrapper) - + setattr(cls, method_name, decorated_method) return cls - + return class_decorator diff --git a/src/components/ChatBox/TaskCard.tsx b/src/components/ChatBox/TaskCard.tsx index 26d7663f7..03a85f8a1 100644 --- a/src/components/ChatBox/TaskCard.tsx +++ b/src/components/ChatBox/TaskCard.tsx @@ -35,6 +35,7 @@ interface TaskCardProps { onUpdateTask: (taskIndex: number, content: string) => void; onDeleteTask: (taskIndex: number) => void; clickable?: boolean; + chatId?: string; } export function TaskCard({ @@ -47,14 +48,15 @@ export function TaskCard({ onUpdateTask, onDeleteTask, clickable = true, + chatId, }: TaskCardProps) { const { t } = useTranslation(); const [isExpanded, setIsExpanded] = useState(true); const contentRef = useRef(null); const [contentHeight, setContentHeight] = useState("auto"); - //Get Chatstore for the active project's task - const { chatStore } = useChatStoreAdapter(); + //Get Chatstore and ProjectStore for the active project's task + const { chatStore, projectStore } = useChatStoreAdapter(); if (!chatStore) { return
Loading...
; } @@ -329,6 +331,20 @@ export function TaskCard({
{ if (task.agent) { + // Switch to the chatStore that owns this task card (for multi-turn conversations) + if (chatId && projectStore.activeProjectId) { + const activeChatStore = projectStore.getActiveChatStore(); + const currentChatId = activeChatStore ? Object.keys(projectStore.projects[projectStore.activeProjectId].chatStores).find( + id => projectStore.projects[projectStore.activeProjectId].chatStores[id] === activeChatStore + ) : null; + + // Only switch if this is a different chat + if (currentChatId !== chatId) { + projectStore.setActiveChatStore(projectStore.activeProjectId, chatId); + } + } + + // Set the active workspace and agent chatStore.setActiveWorkSpace( chatStore.activeTaskId as string, "workflow" diff --git a/src/components/ChatBox/UserQueryGroup.tsx b/src/components/ChatBox/UserQueryGroup.tsx index 7776bba68..a90bc3a35 100644 --- a/src/components/ChatBox/UserQueryGroup.tsx +++ b/src/components/ChatBox/UserQueryGroup.tsx @@ -38,14 +38,14 @@ export const UserQueryGroup: React.FC = ({ // Show task if this query group has a task message OR if it's the most recent user query during splitting // During splitting phase (no to_sub_tasks yet), show task for the most recent query only - const isLastUserQuery = !queryGroup.taskMessage && - activeTaskId && + const isLastUserQuery = !queryGroup.taskMessage && + activeTaskId && chatState.tasks[activeTaskId] && - queryGroup.userMessage && + queryGroup.userMessage && queryGroup.userMessage.id === chatState.tasks[activeTaskId].messages.filter((m: any) => m.role === 'user').pop()?.id && // Only show during active phases (not finished) chatState.tasks[activeTaskId].status !== 'finished'; - + const task = (queryGroup.taskMessage || isLastUserQuery) && activeTaskId ? chatState.tasks[activeTaskId] : null; // Set up intersection observer for this query group @@ -185,6 +185,7 @@ export const UserQueryGroup: React.FC = ({ > 0 || - chatStore.tasks[chatStore.activeTaskId as string].hasMessages || - chatStore.tasks[chatStore.activeTaskId as string].status !== 'pending' + (chatStore.tasks[chatStore.activeTaskId as string]?.messages?.length || 0) > 0 || + chatStore.tasks[chatStore.activeTaskId as string]?.hasMessages || + chatStore.tasks[chatStore.activeTaskId as string]?.status !== 'pending' ) && (