// src/views/AgentChat/hooks/useAgentSessions.ts // 会话管理 Hook - 加载、切换、创建会话 import { useState, useEffect, useCallback } from 'react'; import type { Dispatch, SetStateAction } from 'react'; import axios from 'axios'; import { MessageTypes, type Message } from '../constants/messageTypes'; import { getApiBase } from '@utils/apiConfig'; /** * 会话数据结构 */ export interface Session { session_id: string; title?: string; created_at?: string; timestamp?: string; message_count?: number; } /** * 用户信息(从 AuthContext 传入) */ export interface User { id: string; nickname?: string; avatar?: string; subscription_type?: string; } /** * useAgentSessions Hook 参数 */ export interface UseAgentSessionsParams { /** 当前用户信息 */ user: User | null; /** 消息列表 setter(用于创建新会话时设置欢迎消息) */ setMessages: Dispatch>; } /** * useAgentSessions Hook 返回值 */ export interface UseAgentSessionsReturn { /** 会话列表 */ sessions: Session[]; /** 当前选中的会话 ID */ currentSessionId: string | null; /** 设置当前会话 ID */ setCurrentSessionId: Dispatch>; /** 是否正在加载会话列表 */ isLoadingSessions: boolean; /** 加载会话列表 */ loadSessions: () => Promise; /** 切换到指定会话 */ switchSession: (sessionId: string) => void; /** 创建新会话(显示欢迎消息) */ createNewSession: () => void; /** 加载指定会话的历史消息 */ loadSessionHistory: (sessionId: string) => Promise; } /** * useAgentSessions Hook * * 管理会话列表、会话切换、新建会话逻辑 * * @param params - UseAgentSessionsParams * @returns UseAgentSessionsReturn * * @example * ```tsx * const { * sessions, * currentSessionId, * isLoadingSessions, * switchSession, * createNewSession, * } = useAgentSessions({ user, setMessages }); * ``` */ export const useAgentSessions = ({ user, setMessages, }: UseAgentSessionsParams): UseAgentSessionsReturn => { const [sessions, setSessions] = useState([]); const [currentSessionId, setCurrentSessionId] = useState(null); const [isLoadingSessions, setIsLoadingSessions] = useState(false); /** * 加载用户的会话列表 */ const loadSessions = useCallback(async () => { if (!user?.id) return; setIsLoadingSessions(true); try { const response = await axios.get(`${getApiBase()}/mcp/agent/sessions`, { params: { user_id: String(user.id), limit: 50 }, }); if (response.data.success) { setSessions(response.data.data); } } catch (error) { console.error('加载会话列表失败:', error); } finally { setIsLoadingSessions(false); } }, [user?.id]); /** * 安全解析 JSON 字符串,如果已经是对象则直接返回 */ const safeJsonParse = (value: unknown): unknown => { if (!value) return null; if (typeof value === 'object') return value; if (typeof value === 'string') { try { return JSON.parse(value); } catch { console.warn('JSON 解析失败:', value?.toString().substring(0, 100)); return null; } } return null; }; /** * 加载指定会话的历史消息 */ const loadSessionHistory = useCallback( async (sessionId: string) => { if (!sessionId) return; try { const response = await axios.get(`${getApiBase()}/mcp/agent/history/${sessionId}`, { params: { limit: 100 }, }); if (response.data.success) { const history = response.data.data; const formattedMessages: Message[] = history.map((msg: any, idx: number) => ({ id: `${sessionId}-${idx}`, type: msg.message_type === 'user' ? MessageTypes.USER : MessageTypes.AGENT_RESPONSE, content: msg.message || '', plan: safeJsonParse(msg.plan), stepResults: safeJsonParse(msg.steps), timestamp: msg.timestamp, })); setMessages(formattedMessages); } } catch (error) { console.error('加载会话历史失败:', error); } }, [setMessages] ); /** * 切换到指定会话 */ const switchSession = useCallback( (sessionId: string) => { setCurrentSessionId(sessionId); loadSessionHistory(sessionId); }, [loadSessionHistory] ); /** * 创建新会话(清空消息,显示欢迎消息) */ const createNewSession = useCallback(() => { setCurrentSessionId(null); setMessages([ { id: Date.now(), type: MessageTypes.AGENT_RESPONSE, content: `你好${user?.nickname || ''}!👋\n\n我是**价小前**,你的 AI 投研助手。\n\n**我能做什么?**\n• 📊 全面分析股票基本面和技术面\n• 🔥 追踪市场热点和涨停板块\n• 📈 研究行业趋势和投资机会\n• 📰 汇总最新财经新闻和研报\n\n直接输入你的问题开始探索!`, timestamp: new Date().toISOString(), }, ]); }, [user?.nickname, setMessages]); /** * 组件挂载时加载会话列表并创建新会话 */ useEffect(() => { loadSessions(); createNewSession(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [user]); return { sessions, currentSessionId, setCurrentSessionId, isLoadingSessions, loadSessions, switchSession, createNewSession, loadSessionHistory, }; };