From 5ddf9683b4697195c7da4b7e6d02071e77603d78 Mon Sep 17 00:00:00 2001 From: icarus Date: Fri, 19 Sep 2025 16:39:02 +0800 Subject: [PATCH] feat(chat): add session messages view and active state tracking Implement agent session messages display component and track active topic/session state Add AgentSessionMessages component and integrate with chat view Update topic and session selection to set active state in store --- src/renderer/src/pages/home/Chat.tsx | 54 +++++++++++------ src/renderer/src/pages/home/HomePage.tsx | 2 + .../home/Messages/AgentSessionMessages.tsx | 58 +++++++++++++++++++ .../pages/home/Tabs/components/Sessions.tsx | 3 +- 4 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 src/renderer/src/pages/home/Messages/AgentSessionMessages.tsx diff --git a/src/renderer/src/pages/home/Chat.tsx b/src/renderer/src/pages/home/Chat.tsx index d6d7f08d90..ae0c556483 100644 --- a/src/renderer/src/pages/home/Chat.tsx +++ b/src/renderer/src/pages/home/Chat.tsx @@ -6,6 +6,7 @@ import PromptPopup from '@renderer/components/Popups/PromptPopup' import { QuickPanelProvider } from '@renderer/components/QuickPanel' import { useAssistant } from '@renderer/hooks/useAssistant' import { useChatContext } from '@renderer/hooks/useChatContext' +import { useRuntime } from '@renderer/hooks/useRuntime' import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings' import { useShortcut } from '@renderer/hooks/useShortcuts' import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore' @@ -23,6 +24,7 @@ import styled from 'styled-components' import ChatNavbar from './ChatNavbar' import Inputbar from './Inputbar/Inputbar' +import AgentSessionMessages from './Messages/AgentSessionMessages' import ChatNavigation from './Messages/ChatNavigation' import Messages from './Messages/Messages' import Tabs from './Tabs' @@ -44,6 +46,8 @@ const Chat: FC = (props) => { const { isMultiSelectMode } = useChatContext(props.activeTopic) const { isTopNavbar } = useNavbarPosition() const chatMaxWidth = useChatMaxWidth() + const { chat } = useRuntime() + const { activeTopicOrSession, activeAgentId, activeSessionId } = chat const mainRef = React.useRef(null) const contentSearchRef = React.useRef(null) @@ -136,6 +140,17 @@ const Chat: FC = (props) => { ? 'calc(100vh - var(--navbar-height) - var(--navbar-height) - 12px)' : 'calc(100vh - var(--navbar-height))' + const SessionMessages = () => { + if (activeAgentId === null) { + return
Active Agent ID is invalid.
+ } + const sessionId = activeSessionId[activeAgentId] + if (!sessionId) { + return
Active Session ID is invalid.
+ } + return + } + return ( {isTopNavbar && ( @@ -156,23 +171,28 @@ const Chat: FC = (props) => { justify="space-between" style={{ maxWidth: chatMaxWidth, height: mainHeight }}> - - } - filter={contentSearchFilter} - includeUser={filterIncludeUser} - onIncludeUserChange={userOutlinedItemClickHandler} - /> - {messageNavigation === 'buttons' && } - + {activeTopicOrSession === 'topic' && ( + <> + + } + filter={contentSearchFilter} + includeUser={filterIncludeUser} + onIncludeUserChange={userOutlinedItemClickHandler} + /> + {messageNavigation === 'buttons' && } + + + )} + {activeTopicOrSession === 'session' && } {isMultiSelectMode && } diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index 0e3be2e7b7..f15e893797 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -5,6 +5,7 @@ import { useActiveTopic } from '@renderer/hooks/useTopic' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import NavigationService from '@renderer/services/NavigationService' import { newMessagesActions } from '@renderer/store/newMessage' +import { setActiveTopicOrSessionAction } from '@renderer/store/runtime' import { Assistant, Topic } from '@renderer/types' import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, SECOND_MIN_WINDOW_WIDTH } from '@shared/config/constant' import { AnimatePresence, motion } from 'motion/react' @@ -52,6 +53,7 @@ const HomePage: FC = () => { startTransition(() => { _setActiveTopic((prev) => (newTopic?.id === prev.id ? prev : newTopic)) dispatch(newMessagesActions.setTopicFulfilled({ topicId: newTopic.id, fulfilled: false })) + dispatch(setActiveTopicOrSessionAction('topic')) }) }, [_setActiveTopic, dispatch] diff --git a/src/renderer/src/pages/home/Messages/AgentSessionMessages.tsx b/src/renderer/src/pages/home/Messages/AgentSessionMessages.tsx new file mode 100644 index 0000000000..93bb910f8c --- /dev/null +++ b/src/renderer/src/pages/home/Messages/AgentSessionMessages.tsx @@ -0,0 +1,58 @@ +import ContextMenu from '@renderer/components/ContextMenu' +import Scrollbar from '@renderer/components/Scrollbar' +import { useSession } from '@renderer/hooks/agents/useSession' +import { memo } from 'react' +import styled from 'styled-components' + +import NarrowLayout from './NarrowLayout' + +type Props = { + agentId: string + sessionId: string +} + +const AgentSessionMessages: React.FC = ({ agentId, sessionId }) => { + const { messages } = useSession(agentId, sessionId) + + return ( + + + + + {messages.map((message) => { + const content = message.content.content + if (typeof content === 'string') { + return
{content}
+ } else { + return 'Not string content' + } + })} +
+
+
+
+ ) +} + +const ScrollContainer = styled.div` + display: flex; + flex-direction: column-reverse; + padding: 10px 10px 20px; + .multi-select-mode & { + padding-bottom: 60px; + } +` + +interface ContainerProps { + $right?: boolean +} + +const MessagesContainer = styled(Scrollbar)` + display: flex; + flex-direction: column-reverse; + overflow-x: hidden; + z-index: 1; + position: relative; +` + +export default memo(AgentSessionMessages) diff --git a/src/renderer/src/pages/home/Tabs/components/Sessions.tsx b/src/renderer/src/pages/home/Tabs/components/Sessions.tsx index 95a9cba7e4..4d775ef5ae 100644 --- a/src/renderer/src/pages/home/Tabs/components/Sessions.tsx +++ b/src/renderer/src/pages/home/Tabs/components/Sessions.tsx @@ -2,7 +2,7 @@ import { Button, Spinner } from '@heroui/react' import { SessionModal } from '@renderer/components/Popups/agent/SessionModal' import { useSessions } from '@renderer/hooks/agents/useSessions' import { useAppDispatch } from '@renderer/store' -import { setActiveSessionIdAction } from '@renderer/store/runtime' +import { setActiveSessionIdAction, setActiveTopicOrSessionAction } from '@renderer/store/runtime' import { Plus } from 'lucide-react' import { memo, useCallback } from 'react' import { useTranslation } from 'react-i18next' @@ -23,6 +23,7 @@ const Sessions: React.FC = ({ agentId }) => { const setActiveSessionId = useCallback( (agentId: string, sessionId: string | null) => { dispatch(setActiveSessionIdAction({ agentId, sessionId })) + dispatch(setActiveTopicOrSessionAction('session')) }, [dispatch] )