clean: remove thinking panel + keep reasoning_effort:xhigh in Hermes
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 8s
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 8s
This commit is contained in:
parent
0fc2366eb9
commit
13006ba390
@ -1,8 +1,8 @@
|
||||
import { useState, useRef, useEffect, useCallback } from 'react'
|
||||
import { Input, Button, Avatar, theme, Typography, App, Collapse } from 'antd'
|
||||
import { Input, Button, Avatar, theme, Typography, App } from 'antd'
|
||||
import {
|
||||
SendOutlined, RobotOutlined, UserOutlined, PlusOutlined,
|
||||
DeleteOutlined, StopOutlined, MessageOutlined, BulbOutlined, ToolOutlined, LoadingOutlined,
|
||||
DeleteOutlined, StopOutlined, MessageOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { streamChat, type StreamEvent } from '@/services/ai-chat'
|
||||
import {
|
||||
@ -18,8 +18,6 @@ interface Message {
|
||||
role: 'user' | 'assistant'
|
||||
content: string
|
||||
timestamp: number
|
||||
thinking?: string
|
||||
toolCalls?: { name: string; result?: string }[]
|
||||
streaming?: boolean
|
||||
}
|
||||
|
||||
@ -103,8 +101,6 @@ function ChatPage() {
|
||||
setMessages(prev => [...prev, streamMsg])
|
||||
|
||||
let currentContent = ''
|
||||
let currentThinking = ''
|
||||
const currentTools: { name: string; result?: string }[] = []
|
||||
let completedConvId: string | undefined
|
||||
|
||||
const update = (updates: Partial<Message>) =>
|
||||
@ -118,25 +114,12 @@ function ChatPage() {
|
||||
switch (event.event) {
|
||||
case 'meta':
|
||||
completedConvId = event.conversationId
|
||||
if (event.conversationId && event.conversationId !== activeId) {
|
||||
setActiveId(event.conversationId); loadConversations()
|
||||
}
|
||||
if (event.conversationId && event.conversationId !== activeId) { setActiveId(event.conversationId); loadConversations() }
|
||||
break
|
||||
case 'message.delta':
|
||||
currentContent += event.delta || ''
|
||||
update({ content: currentContent, streaming: true })
|
||||
break
|
||||
case 'reasoning.available':
|
||||
currentThinking = event.text || ''
|
||||
update({ thinking: currentThinking })
|
||||
break
|
||||
case 'tool.start':
|
||||
currentTools.push({ name: event.toolName || 'unknown' })
|
||||
update({ toolCalls: [...currentTools] })
|
||||
break
|
||||
case 'tool.result':
|
||||
if (currentTools.length > 0) { currentTools[currentTools.length - 1].result = event.output || ''; update({ toolCalls: [...currentTools] }) }
|
||||
break
|
||||
case 'run.completed':
|
||||
if (event.output) currentContent = event.output
|
||||
update({ content: currentContent, streaming: false })
|
||||
@ -164,7 +147,6 @@ function ChatPage() {
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', height: 'calc(100vh - 112px)', gap: 12 }}>
|
||||
{/* Sidebar */}
|
||||
<div style={{ width: 260, flexShrink: 0, display: 'flex', flexDirection: 'column', background: token.colorBgContainer, borderRadius: token.borderRadiusLG, border: `1px solid ${token.colorBorderSecondary}`, overflow: 'hidden' }}>
|
||||
<div style={{ padding: 12, borderBottom: `1px solid ${token.colorBorderSecondary}` }}>
|
||||
<Button type="primary" icon={<PlusOutlined />} block onClick={handleNew}>新对话</Button>
|
||||
@ -190,14 +172,13 @@ function ChatPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Chat */}
|
||||
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
|
||||
<div style={{ flex: 1, overflowY: 'auto', background: token.colorBgContainer, borderRadius: `${token.borderRadiusLG}px ${token.borderRadiusLG}px 0 0`, padding: '20px 24px', border: `1px solid ${token.colorBorderSecondary}`, borderBottom: 'none' }}>
|
||||
{messages.length === 0 && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
|
||||
<RobotOutlined style={{ fontSize: 48, marginBottom: 16, color: token.colorTextQuaternary }} />
|
||||
<Text type="secondary" style={{ fontSize: 16 }}>{activeId ? '开始新对话' : '点击「新对话」开始'}</Text>
|
||||
<Text type="secondary" style={{ fontSize: 13, marginTop: 8 }}>Hermes Agent · 流式响应 · 思考过程可见</Text>
|
||||
<Text type="secondary" style={{ fontSize: 13, marginTop: 8 }}>Hermes Agent · 流式响应 · xhigh 推理</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -206,31 +187,11 @@ function ChatPage() {
|
||||
<Avatar size={32} icon={msg.role === 'user' ? <UserOutlined /> : <RobotOutlined />}
|
||||
style={{ backgroundColor: msg.role === 'user' ? token.colorPrimary : token.colorSuccess, flexShrink: 0 }} />
|
||||
<div style={{ maxWidth: '75%', minWidth: 0 }}>
|
||||
{/* Thinking — auto expand during streaming */}
|
||||
{msg.thinking && msg.thinking !== msg.content && (
|
||||
<Collapse size="small" ghost defaultActiveKey={[]} items={[{
|
||||
key: 'thinking', label: <Text style={{ fontSize: 12, color: token.colorTextSecondary }}><BulbOutlined /> 思考过程{msg.streaming ? <LoadingOutlined style={{ marginLeft: 6, fontSize: 11 }} spin /> : null}</Text>,
|
||||
children: <div style={{ fontSize: 13, color: token.colorTextSecondary, whiteSpace: 'pre-wrap', lineHeight: 1.7, maxHeight: 200, overflowY: 'auto', padding: '4px 0' }}>{msg.thinking}</div>,
|
||||
}]} style={{ marginBottom: 8, background: 'transparent' }} />
|
||||
)}
|
||||
{/* Tools */}
|
||||
{msg.toolCalls && msg.toolCalls.length > 0 && (
|
||||
<Collapse size="small" ghost items={[{
|
||||
key: 'tools', label: <Text style={{ fontSize: 12, color: token.colorTextSecondary }}><ToolOutlined /> 工具调用 ({msg.toolCalls.length})</Text>,
|
||||
children: msg.toolCalls.map((t, i) => (
|
||||
<div key={i} style={{ marginBottom: 8, fontSize: 12 }}>
|
||||
<Text code style={{ fontSize: 12 }}>{t.name}</Text>
|
||||
{t.result && <div style={{ marginTop: 4, color: token.colorTextSecondary, maxHeight: 150, overflowY: 'auto', whiteSpace: 'pre-wrap' }}>{t.result}</div>}
|
||||
</div>
|
||||
)),
|
||||
}]} style={{ marginBottom: 8, background: 'transparent' }} />
|
||||
)}
|
||||
{/* Content */}
|
||||
<div style={{ padding: '12px 16px', borderRadius: 12, lineHeight: 1.8, wordBreak: 'break-word', background: msg.role === 'user' ? token.colorPrimary : token.colorFillAlter, color: msg.role === 'user' ? '#fff' : token.colorText }}>
|
||||
{msg.role === 'assistant'
|
||||
? (msg.content
|
||||
? <Markdown content={msg.content + (msg.streaming ? '▊' : '')} />
|
||||
: <Text type="secondary" style={{ fontSize: 13 }}><LoadingOutlined spin style={{ marginRight: 6 }} />思考中...</Text>)
|
||||
: <Text type="secondary" style={{ fontSize: 13 }}>思考中...</Text>)
|
||||
: msg.content}
|
||||
</div>
|
||||
</div>
|
||||
@ -239,23 +200,15 @@ function ChatPage() {
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
|
||||
{/* Input */}
|
||||
<div style={{ background: token.colorBgContainer, border: `1px solid ${token.colorBorderSecondary}`, borderRadius: `0 0 ${token.borderRadiusLG}px ${token.borderRadiusLG}px`, padding: '16px 20px' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 10, background: token.colorFillTertiary, borderRadius: 12, padding: '8px 8px 8px 14px', border: `1px solid ${token.colorBorderSecondary}` }}>
|
||||
<Input.TextArea value={input}
|
||||
onChange={e => setInput(e.target.value)}
|
||||
<Input.TextArea value={input} onChange={e => setInput(e.target.value)}
|
||||
onCompositionStart={() => { composingRef.current = true }}
|
||||
onCompositionEnd={() => { composingRef.current = false }}
|
||||
onKeyDown={e => {
|
||||
if (composingRef.current) return
|
||||
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend() }
|
||||
}}
|
||||
placeholder={activeId ? '输入消息,Enter 发送,Shift+Enter 换行' : '请先新建或选择对话'}
|
||||
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||
disabled={streaming || !activeId}
|
||||
variant="borderless"
|
||||
style={{ flex: 1, resize: 'none', padding: '4px 0', fontSize: 14 }}
|
||||
/>
|
||||
onKeyDown={e => { if (composingRef.current) return; if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend() } }}
|
||||
placeholder={activeId ? '输入消息,Enter 发送' : '请先新建或选择对话'}
|
||||
autoSize={{ minRows: 1, maxRows: 5 }} disabled={streaming || !activeId}
|
||||
variant="borderless" style={{ flex: 1, resize: 'none', padding: '4px 0', fontSize: 14 }} />
|
||||
{streaming ? (
|
||||
<Button danger type="primary" icon={<StopOutlined />} onClick={handleStop} style={{ borderRadius: 8, height: 34, minWidth: 72 }}>停止</Button>
|
||||
) : (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user