fix: remove reason in message bottom

main
yannyang 2026-07-27 22:32:28 +08:00
parent 67585d17ce
commit f1553be178
3 changed files with 149 additions and 62 deletions

View File

@ -139,12 +139,15 @@ export default function MessageItem(props: {
)} )}
</div> </div>
{/* 展示 RAG 和 工具调用 */} {/* 底部 Meta 信息展示 (RAG / Tool) */}
{!isMobile && message.meta && !isUser && ( {!isMobile && message.meta && !isUser && (
<div style={{ marginTop: 8 }}> <div className="message-meta-section">
{!!message.meta.reasoning && <ReasoningView reasoning={message.meta.reasoning} />} {message.meta.retrieved && message.meta.retrieved.length > 0 && (
{!!message.meta.retrieved?.length && <RetrievedView retrieved={message.meta.retrieved} />} <RetrievedView retrieved={message.meta.retrieved} />
{!!message.meta.toolCalls?.length && <ToolCallView calls={message.meta.toolCalls} />} )}
{message.meta.toolCalls && message.meta.toolCalls.length > 0 && (
<ToolCallView calls={message.meta.toolCalls} />
)}
</div> </div>
)} )}
</div> </div>

View File

@ -0,0 +1,124 @@
.reasoning-container {
margin: 4px 0;
transition: all 0.3s ease;
}
.reasoning-header {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
user-select: none;
padding: 4px 0;
border-radius: 4px;
transition: background-color 0.2s;
}
.reasoning-header:hover {
background-color: var(--color-surface-2);
}
.reasoning-label {
font-size: 12px;
color: var(--color-text-tertiary);
font-weight: 500;
}
.reasoning-toggle-icon {
font-size: 10px;
color: var(--color-text-tertiary);
transition: transform 0.2s;
}
.reasoning-container.is-expanded .reasoning-toggle-icon {
transform: rotate(90deg);
}
.reasoning-content {
font-size: 13px;
color: var(--color-text-secondary);
line-height: 1.6;
overflow: auto;
border-left: 2px solid var(--color-border-light);
padding-left: 12px;
margin-left: 4px;
margin-top: 8px;
animation: reasoningFadeIn 0.3s ease-out;
}
@keyframes reasoningFadeIn {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* RAG View Styles */
.retrieved-label {
font-size: 12px;
color: #6366f1;
}
.retrieved-list {
font-size: 12px;
}
.retrieved-item {
padding: 8px;
background: #f6f8ff;
border-radius: 6px;
margin-bottom: 6px;
border-left: 3px solid #6366f1;
}
.retrieved-item-header {
color: #6366f1;
font-weight: 600;
margin-bottom: 4px;
}
.retrieved-item-preview {
color: #374151;
white-space: pre-wrap;
}
/* Tool Call View Styles */
.tool-call-label {
font-size: 12px;
color: #f97316;
}
.tool-call-list {
font-size: 12px;
}
.tool-call-item {
padding: 8px;
background: #fff7ed;
border-radius: 6px;
margin-bottom: 6px;
border-left: 3px solid #f97316;
}
.tool-call-item-header {
color: #c2410c;
font-weight: 600;
margin-bottom: 4px;
}
.tool-call-item-args {
color: #6b7280;
}
.tool-call-item-result {
color: #374151;
margin-top: 4px;
}
.tool-call-item-result code {
word-break: break-all;
}

View File

@ -2,6 +2,7 @@ import { Collapse, Tag } from 'antd';
import { RightOutlined } from '@ant-design/icons'; import { RightOutlined } from '@ant-design/icons';
import type { RetrievedSnippet, ToolCallTrace } from '../../../../api'; import type { RetrievedSnippet, ToolCallTrace } from '../../../../api';
import Markdown from '../../../../components/Markdown'; import Markdown from '../../../../components/Markdown';
import './MetaViews.css';
export function ReasoningView({ export function ReasoningView({
reasoning, reasoning,
@ -14,35 +15,12 @@ export function ReasoningView({
}) { }) {
return ( return (
<div className={`reasoning-container ${expanded ? 'is-expanded' : ''}`}> <div className={`reasoning-container ${expanded ? 'is-expanded' : ''}`}>
<div className="reasoning-header" onClick={onToggle} style={{ <div className="reasoning-header" onClick={onToggle}>
display: 'flex', <span className="reasoning-label"></span>
alignItems: 'center', <RightOutlined className="reasoning-toggle-icon" />
gap: 6,
cursor: 'pointer',
userSelect: 'none',
marginBottom: expanded ? 8 : 0
}}>
<span style={{ fontSize: 12, color: 'var(--color-text-tertiary)', fontWeight: 500 }}>
</span>
<RightOutlined style={{
fontSize: 10,
color: 'var(--color-text-tertiary)',
transition: 'transform 0.2s',
transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)'
}} />
</div> </div>
{expanded && ( {expanded && (
<div className="reasoning-content" style={{ <div className="reasoning-content">
fontSize: 13,
color: 'var(--color-text-secondary)',
lineHeight: 1.6,
maxHeight: 300,
overflow: 'auto',
borderLeft: '2px solid var(--color-border-light)',
paddingLeft: 12,
marginLeft: 4
}}>
<Markdown>{reasoning}</Markdown> <Markdown>{reasoning}</Markdown>
</div> </div>
)} )}
@ -58,24 +36,15 @@ export function RetrievedView({ retrieved }: { retrieved: RetrievedSnippet[] })
items={[ items={[
{ {
key: 'rag', key: 'rag',
label: <span style={{ fontSize: 12, color: '#6366f1' }}>🔍 RAG ({retrieved.length})</span>, label: <span className="retrieved-label">RAG ({retrieved.length})</span>,
children: ( children: (
<div style={{ fontSize: 12 }}> <div className="retrieved-list">
{retrieved.map((r, i) => ( {retrieved.map((r, i) => (
<div <div key={i} className="retrieved-item">
key={i} <div className="retrieved-item-header">
style={{
padding: 8,
background: '#f6f8ff',
borderRadius: 6,
marginBottom: 6,
borderLeft: '3px solid #6366f1'
}}
>
<div style={{ color: '#6366f1', fontWeight: 600, marginBottom: 4 }}>
📄 {r.fileName} · #{r.chunkIndex} · score {r.score.toFixed(3)} 📄 {r.fileName} · #{r.chunkIndex} · score {r.score.toFixed(3)}
</div> </div>
<div style={{ color: '#374151', whiteSpace: 'pre-wrap' }}> <div className="retrieved-item-preview">
{r.preview} {r.preview}
{r.preview.length >= 200 ? '…' : ''} {r.preview.length >= 200 ? '…' : ''}
</div> </div>
@ -98,35 +67,26 @@ export function ToolCallView({ calls, liveStyle }: { calls: ToolCallTrace[]; liv
items={[ items={[
{ {
key: 'tc', key: 'tc',
label: <span style={{ fontSize: 12, color: '#f97316' }}>🛠 ({calls.length})</span>, label: <span className="tool-call-label">🛠 ({calls.length})<RightOutlined /></span>,
children: ( children: (
<div style={{ fontSize: 12 }}> <div className="tool-call-list">
{calls.map((t, i) => { {calls.map((t, i) => {
const isPending = (t.result as any)?.pending; const isPending = (t.result as any)?.pending;
const isFailed = t.result?.ok === false; const isFailed = t.result?.ok === false;
return ( return (
<div <div key={i} className="tool-call-item">
key={i} <div className="tool-call-item-header">
style={{
padding: 8,
background: '#fff7ed',
borderRadius: 6,
marginBottom: 6,
borderLeft: '3px solid #f97316'
}}
>
<div style={{ color: '#c2410c', fontWeight: 600, marginBottom: 4 }}>
{t.name} {isPending && <Tag color="processing"></Tag>} {t.name} {isPending && <Tag color="processing"></Tag>}
{!isPending && t.result?.durationMs != null && <Tag>{t.result.durationMs}ms</Tag>} {!isPending && t.result?.durationMs != null && <Tag>{t.result.durationMs}ms</Tag>}
{isFailed && <Tag color="error"></Tag>} {isFailed && <Tag color="error"></Tag>}
</div> </div>
<div style={{ color: '#6b7280' }}> <div className="tool-call-item-args">
<b>args:</b> {JSON.stringify(t.args)} <b>args:</b> {JSON.stringify(t.args)}
</div> </div>
{!isPending && ( {!isPending && (
<div style={{ color: '#374151', marginTop: 4 }}> <div className="tool-call-item-result">
<b>result:</b>{' '} <b>result:</b>{' '}
<code style={{ wordBreak: 'break-all' }}> <code>
{JSON.stringify(t.result?.result ?? t.result?.error ?? t.result).slice(0, 500)} {JSON.stringify(t.result?.result ?? t.result?.error ?? t.result).slice(0, 500)}
</code> </code>
</div> </div>