diff --git a/src/renderer/src/hooks/agents/useAgentSessionInitializer.ts b/src/renderer/src/hooks/agents/useAgentSessionInitializer.ts new file mode 100644 index 0000000000..23161b4223 --- /dev/null +++ b/src/renderer/src/hooks/agents/useAgentSessionInitializer.ts @@ -0,0 +1,80 @@ +import { loggerService } from '@logger' +import { useRuntime } from '@renderer/hooks/useRuntime' +import { useAppDispatch } from '@renderer/store' +import { setActiveSessionIdAction, setActiveTopicOrSessionAction } from '@renderer/store/runtime' +import { useCallback, useEffect } from 'react' + +import { useAgentClient } from './useAgentClient' + +const logger = loggerService.withContext('useAgentSessionInitializer') + +/** + * Hook to automatically initialize and load the latest session for an agent + * when the agent is activated. This ensures that when switching to an agent, + * its most recent session is automatically selected. + */ +export const useAgentSessionInitializer = () => { + const dispatch = useAppDispatch() + const client = useAgentClient() + const { chat } = useRuntime() + const { activeAgentId, activeSessionId } = chat + + /** + * Initialize session for the given agent by loading its sessions + * and setting the latest one as active + */ + const initializeAgentSession = useCallback( + async (agentId: string) => { + if (!agentId || agentId === 'fake') return + + try { + // Check if this agent already has an active session + const currentSessionId = activeSessionId[agentId] + if (currentSessionId) { + // Session already exists, just switch to session view + dispatch(setActiveTopicOrSessionAction('session')) + return + } + + // Load sessions for this agent + const response = await client.listSessions(agentId) + const sessions = response.data + + if (sessions && sessions.length > 0) { + // Get the latest session (first in the list, assuming they're sorted by updatedAt) + const latestSession = sessions[0] + + // Set the latest session as active + dispatch(setActiveSessionIdAction({ agentId, sessionId: latestSession.id })) + dispatch(setActiveTopicOrSessionAction('session')) + } else { + // No sessions exist, we might want to create one + // But for now, just switch to session view and let the Sessions component handle it + dispatch(setActiveTopicOrSessionAction('session')) + } + } catch (error) { + logger.error('Failed to initialize agent session:', error as Error) + // Even if loading fails, switch to session view + dispatch(setActiveTopicOrSessionAction('session')) + } + }, + [client, dispatch, activeSessionId] + ) + + /** + * Auto-initialize when activeAgentId changes + */ + useEffect(() => { + if (activeAgentId && activeAgentId !== 'fake') { + // Check if we need to initialize this agent's session + const hasActiveSession = activeSessionId[activeAgentId] + if (!hasActiveSession) { + initializeAgentSession(activeAgentId) + } + } + }, [activeAgentId, activeSessionId, initializeAgentSession]) + + return { + initializeAgentSession + } +} diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index 5b8bd93bfd..cd18552a3e 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -1,4 +1,5 @@ import { ErrorBoundary } from '@renderer/components/ErrorBoundary' +import { useAgentSessionInitializer } from '@renderer/hooks/agents/useAgentSessionInitializer' import { useAssistants } from '@renderer/hooks/useAssistant' import { useRuntime } from '@renderer/hooks/useRuntime' import { useNavbarPosition, useSettings } from '@renderer/hooks/useSettings' @@ -26,6 +27,9 @@ const HomePage: FC = () => { const navigate = useNavigate() const { isLeftNavbar } = useNavbarPosition() + // Initialize agent session hook + useAgentSessionInitializer() + const location = useLocation() const state = location.state @@ -108,9 +112,9 @@ const HomePage: FC = () => { createdAt: '', updatedAt: '', messages: [] - } + } as unknown as Topic ], - type: '' + type: 'chat' }) } else if (activeTopicOrSession === 'topic') { dispatch(setActiveAgentId('fake')) diff --git a/src/renderer/src/pages/home/Tabs/components/Agents.tsx b/src/renderer/src/pages/home/Tabs/components/Agents.tsx index 253f0888a0..406d7837fc 100644 --- a/src/renderer/src/pages/home/Tabs/components/Agents.tsx +++ b/src/renderer/src/pages/home/Tabs/components/Agents.tsx @@ -1,9 +1,10 @@ import { Alert, Button, Spinner } from '@heroui/react' import { AgentModal } from '@renderer/components/Popups/agent/AgentModal' import { useAgents } from '@renderer/hooks/agents/useAgents' +import { useAgentSessionInitializer } from '@renderer/hooks/agents/useAgentSessionInitializer' import { useRuntime } from '@renderer/hooks/useRuntime' import { useAppDispatch } from '@renderer/store' -import { setActiveAgentId as setActiveAgentIdAction, setActiveTopicOrSessionAction } from '@renderer/store/runtime' +import { setActiveAgentId as setActiveAgentIdAction } from '@renderer/store/runtime' import { Plus } from 'lucide-react' import { FC, useCallback, useEffect } from 'react' import { useTranslation } from 'react-i18next' @@ -17,14 +18,17 @@ export const Agents: FC = () => { const { t } = useTranslation() const { chat } = useRuntime() const { activeAgentId } = chat + const { initializeAgentSession } = useAgentSessionInitializer() const dispatch = useAppDispatch() const setActiveAgentId = useCallback( - (id: string) => { + async (id: string) => { dispatch(setActiveAgentIdAction(id)) + // Initialize the session for this agent + await initializeAgentSession(id) }, - [dispatch] + [dispatch, initializeAgentSession] ) useEffect(() => { @@ -47,7 +51,6 @@ export const Agents: FC = () => { onDelete={() => deleteAgent(agent.id)} onPress={() => { setActiveAgentId(agent.id) - dispatch(setActiveTopicOrSessionAction('session')) }} /> ))}