diff --git a/mcp_server.py b/mcp_server.py index 971a94e5..a71f2bee 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -1679,6 +1679,9 @@ async def agent_chat(request: AgentChatRequest): ensure_ascii=False ) + # 将 plan 转换为 JSON 字符串(ES 中 plan 字段是 text 类型) + plan_json = json.dumps(response.plan.dict(), ensure_ascii=False) if response.plan else None + es_client.save_chat_message( session_id=session_id, user_id=request.user_id or "anonymous", @@ -1686,7 +1689,7 @@ async def agent_chat(request: AgentChatRequest): user_avatar=request.user_avatar or "", message_type="assistant", message=response.final_summary, # 使用 final_summary 而不是 final_answer - plan=response.plan.dict() if response.plan else None, # 转换为字典 + plan=plan_json, # 传递 JSON 字符串而不是字典 steps=steps_json, ) except Exception as e: diff --git a/src/views/AgentChat/index.js b/src/views/AgentChat/index.js index 738e255a..f262d420 100644 --- a/src/views/AgentChat/index.js +++ b/src/views/AgentChat/index.js @@ -217,7 +217,7 @@ const AgentChatV3 = () => { setMessages((prev) => [...prev, { ...message, id: Date.now() }]); }; - // 发送消息 + // 发送消息(流式 SSE 版本) const handleSendMessage = async () => { if (!inputValue.trim() || isProcessing) return; @@ -242,10 +242,10 @@ const AgentChatV3 = () => { return; } - logger.info('AgentChat', '权限检查通过', { - userId: user?.id, - username: user?.username, - subscription_type: user?.subscription_type + logger.info('AgentChat', '权限检查通过', { + userId: user?.id, + username: user?.username, + subscription_type: user?.subscription_type }); const userMessage = { @@ -262,6 +262,7 @@ const AgentChatV3 = () => { let currentPlan = null; let stepResults = []; + let executingMessageId = null; try { // 1. 显示思考状态 @@ -273,8 +274,8 @@ const AgentChatV3 = () => { setCurrentProgress(10); - // 2. 调用后端API(非流式) - const response = await axios.post('/mcp/agent/chat', { + // 2. 使用 EventSource 接收 SSE 流式数据 + const requestBody = { message: userInput, conversation_history: messages .filter((m) => m.type === MessageTypes.USER || m.type === MessageTypes.AGENT_RESPONSE) @@ -285,54 +286,140 @@ const AgentChatV3 = () => { user_id: user?.id ? String(user.id) : 'anonymous', user_nickname: user?.nickname || user?.username || '匿名用户', user_avatar: user?.avatar || '', - subscription_type: user?.subscription_type || 'free', // 传递订阅类型 + subscription_type: user?.subscription_type || 'free', session_id: currentSessionId, + }; + + // 使用 fetch API 进行 SSE 请求 + const response = await fetch('/mcp/agent/chat/stream', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), }); - // 移除思考消息 - setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_THINKING)); - - if (response.data.success) { - const data = response.data; - - // 更新 session_id(如果是新会话) - if (data.session_id && !currentSessionId) { - setCurrentSessionId(data.session_id); - } - - // 显示执行计划 - if (data.plan) { - currentPlan = data.plan; - addMessage({ - type: MessageTypes.AGENT_PLAN, - content: '已制定执行计划', - plan: data.plan, - timestamp: new Date().toISOString(), - }); - setCurrentProgress(30); - } - - // 显示执行步骤 - if (data.step_results && data.step_results.length > 0) { - stepResults = data.step_results; - setCurrentProgress(70); - } - - // 显示最终结果(包含执行步骤) - addMessage({ - type: MessageTypes.AGENT_RESPONSE, - content: data.final_summary || data.message || '处理完成', - plan: currentPlan, - stepResults: stepResults, - metadata: data.metadata, - timestamp: new Date().toISOString(), - }); - - setCurrentProgress(100); - - // 重新加载会话列表 - loadSessions(); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); } + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + // 读取流式数据 + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop(); // 保留不完整的行 + + for (const line of lines) { + if (!line.trim() || line.startsWith(':')) continue; + + if (line.startsWith('event:')) { + // 忽略事件类型行 + continue; + } + + if (line.startsWith('data:')) { + try { + const data = JSON.parse(line.substring(5).trim()); + + // 处理不同类型的事件 + if (data.stage === 'planning') { + // 正在制定计划 + setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_THINKING)); + addMessage({ + type: MessageTypes.AGENT_THINKING, + content: '正在制定执行计划...', + timestamp: new Date().toISOString(), + }); + setCurrentProgress(20); + } else if (data.goal) { + // 收到执行计划 + currentPlan = data; + setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_THINKING)); + addMessage({ + type: MessageTypes.AGENT_PLAN, + content: '已制定执行计划', + plan: data, + timestamp: new Date().toISOString(), + }); + setCurrentProgress(30); + } else if (data.stage === 'executing') { + // 开始执行步骤 + const msgId = Date.now(); + executingMessageId = msgId; + addMessage({ + id: msgId, + type: MessageTypes.AGENT_EXECUTING, + content: `正在执行 ${data.message}`, + plan: currentPlan, + stepResults: [], + timestamp: new Date().toISOString(), + }); + setCurrentProgress(40); + } else if (data.step_index !== undefined && data.tool) { + // 收到步骤完成事件 + const stepResult = { + step_index: data.step_index, + tool: data.tool, + status: data.status, + result: data.result, + error: data.error, + execution_time: data.execution_time, + }; + stepResults.push(stepResult); + + // 更新执行中的消息 + setMessages((prev) => + prev.map((m) => + m.id === executingMessageId + ? { ...m, stepResults: [...stepResults] } + : m + ) + ); + + // 更新进度 + const progress = 40 + (stepResults.length / (currentPlan?.steps?.length || 5)) * 40; + setCurrentProgress(Math.min(progress, 80)); + } else if (data.stage === 'summarizing') { + // 正在生成总结 + setMessages((prev) => prev.filter((m) => m.type !== MessageTypes.AGENT_EXECUTING)); + addMessage({ + type: MessageTypes.AGENT_THINKING, + content: '正在生成分析报告...', + timestamp: new Date().toISOString(), + }); + setCurrentProgress(85); + } else if (data.content) { + // 收到最终总结 + setMessages((prev) => + prev.filter((m) => m.type !== MessageTypes.AGENT_THINKING && m.type !== MessageTypes.AGENT_EXECUTING) + ); + addMessage({ + type: MessageTypes.AGENT_RESPONSE, + content: data.content, + plan: currentPlan, + stepResults: stepResults, + metadata: data.metadata, + timestamp: new Date().toISOString(), + }); + setCurrentProgress(100); + } + } catch (e) { + logger.error('解析 SSE 数据失败', e); + } + } + } + } + + // 重新加载会话列表 + loadSessions(); + } catch (error) { logger.error('Agent chat error', error); @@ -343,7 +430,7 @@ const AgentChatV3 = () => { ) ); - const errorMessage = error.response?.data?.error || error.message || '处理失败'; + const errorMessage = error.response?.data?.detail || error.message || '处理失败'; addMessage({ type: MessageTypes.ERROR,