diff --git a/docker-compose.yml b/docker-compose.yml index cad6149..77f8f19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: build: context: . dockerfile: Dockerfile - image: tradus-web:1.5 + image: tradus-web:1.6 container_name: tradus-web ports: - '6000:80' diff --git a/src/views/AIAgentView.vue b/src/views/AIAgentView.vue index 396ed6c..0eb25b7 100644 --- a/src/views/AIAgentView.vue +++ b/src/views/AIAgentView.vue @@ -166,24 +166,6 @@ watch(selectedAgent, (newAgent) => { } }) -// 获取当前agent的会话ID -const getConversationId = (agentId: string) => { - const key = `conversation_${agentId}` - return localStorage.getItem(key) -} - -// 保存当前agent的会话ID -const saveConversationId = (agentId: string, conversationId: string) => { - const key = `conversation_${agentId}` - localStorage.setItem(key, conversationId) -} - -// 清除当前agent的会话ID -const clearConversationId = (agentId: string) => { - const key = `conversation_${agentId}` - localStorage.removeItem(key) -} - const showConfirmDialog = ref(false) const confirmDialogTitle = ref('') const confirmDialogMessage = ref('') @@ -201,13 +183,11 @@ const selectAgent = (agent: Agent) => { if (!selectedAgent.value || agent.id !== selectedAgent.value.id) { // 直接切换到新的 Agent selectedAgent.value = agent - clearConversationId(agent.id) chatHistory.value = [] addInitialGreeting(agent).catch(console.error) } else { // 点击当前 Agent,显示确认框 showConfirm('重新开始对话', '是否重新开启新会话?', () => { - clearConversationId(agent.id) chatHistory.value = [] addInitialGreeting(agent).catch(console.error) showConfirmDialog.value = false @@ -257,9 +237,6 @@ const sendMessage = async () => { headers['Authorization'] = userStore.authHeader } - // 获取当前agent的会话ID - const conversationId = selectedAgent.value ? getConversationId(selectedAgent.value.id) : null - // 调用流式接口 const response = await fetch(`${apiBaseUrl}/agent/chat`, { method: 'POST', @@ -267,12 +244,13 @@ const sendMessage = async () => { body: JSON.stringify({ user_prompt: currentInput, agent_id: selectedAgent.value.id, - conversation_id: conversationId, }), }) if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`) + const errorText = await response.text() + console.error('API响应错误:', response.status, errorText) + throw new Error(`服务器响应错误: ${response.status} - ${errorText || '未知错误'}`) } const reader = response.body?.getReader() @@ -281,6 +259,7 @@ const sendMessage = async () => { } const decoder = new TextDecoder() + let buffer = '' // 用于存储不完整的JSON数据 // 处理流式响应 while (true) { @@ -288,18 +267,20 @@ const sendMessage = async () => { if (done) break const chunk = decoder.decode(value, { stream: true }) - const lines = chunk.split('\n') + buffer += chunk + + // 处理可能的多行数据 + const lines = buffer.split('\n') + // 保留最后一行(可能不完整) + buffer = lines.pop() || '' for (const line of lines) { if (!line.trim() || !line.startsWith('data: ')) continue try { - const data = JSON.parse(line.slice(6)) - - // 处理 conversation_id - if (data.conversation_id && selectedAgent.value) { - saveConversationId(selectedAgent.value.id, data.conversation_id) - } + const jsonStr = line.slice(6) // 移除 "data: " 前缀 + console.log('收到的JSON数据:', jsonStr) // 调试日志 + const data = JSON.parse(jsonStr) switch (data.event) { case 'agent_message': @@ -312,7 +293,7 @@ const sendMessage = async () => { case 'agent_thought': if (data.tool) { - const thoughtText = `Agent 正在调用 ${data.tool} 工具` + const thoughtText = `Agent 正在调用 ${data.tool} 工具` chatHistory.value[tempMessageIndex].content = currentResponseText.value ? `${thoughtText}\n\n${currentResponseText.value}` : thoughtText @@ -320,35 +301,36 @@ const sendMessage = async () => { } break - case 'message_file': - if (data.type === 'image') { - // 找到最后一条助手消息来添加文件 - const lastIndex = chatHistory.value.length - 1 - if (chatHistory.value[lastIndex].role === 'assistant') { - chatHistory.value[lastIndex].files.push({ - type: 'image', - url: data.url, - }) - } - } + case 'error': + const errorMessage = data.error || '未知错误' + chatHistory.value[tempMessageIndex].content = + `抱歉,处理您的请求时出错了:${errorMessage}` + isLoading.value = false + await scrollToBottom() break case 'message_end': - break - - case 'tts_message': - // 处理语音合成消息 + if (currentResponseText.value.trim()) { + chatHistory.value[tempMessageIndex].content = currentResponseText.value + } break } } catch (e) { - console.error('解析响应数据出错:', e) + console.error('解析JSON数据出错:', e, '原始数据:', line) + if (line.includes('') || line.includes('')) { + chatHistory.value[tempMessageIndex].content = + '抱歉,服务器返回了错误的响应格式,请稍后再试。' + } else { + chatHistory.value[tempMessageIndex].content = '抱歉,解析响应数据时出错了,请稍后再试。' + } + await scrollToBottom() } } } } catch (error) { console.error('调用API出错:', error) - // 更新错误消息 - chatHistory.value[tempMessageIndex].content = '抱歉,请求出错了。请稍后再试。' + const errorMessage = error instanceof Error ? error.message : '未知错误' + chatHistory.value[tempMessageIndex].content = `抱歉,请求出错了:${errorMessage}` await scrollToBottom() } finally { isLoading.value = false @@ -420,7 +402,7 @@ const getInitial = (nickname: string) => { : 'ai-message', ]" > -
+
{ border: 1px solid var(--color-border); } -.user-message .avatar { - order: 1; +.user-avatar { background-color: var(--color-accent); + color: white; + font-size: 1.1rem; + font-weight: 500; border: none; } -.user-message .avatar svg { - color: white; +.ai-avatar { + background-color: var(--color-bg-secondary); + border: 1px solid var(--color-border); } -.avatar svg { +.ai-avatar svg { width: 24px; height: 24px; color: var(--color-accent); @@ -783,14 +768,14 @@ const getInitial = (nickname: string) => { .user-message .message-content { background-color: var(--color-accent); color: white; - border-radius: 1rem 0 1rem 1rem; + border-radius: 0 1rem 1rem 1rem; padding: 1.25rem; } .ai-message .message-content { background-color: var(--color-bg-secondary); color: var(--color-text-primary); - border-radius: 0 1rem 1rem 1rem; + border-radius: 1rem 0 1rem 1rem; border: 1px solid var(--color-border); padding: 1.25rem; margin-top: 0.5rem;