116 lines
3.9 KiB
TypeScript
116 lines
3.9 KiB
TypeScript
import { Collapse, Tag } from 'antd';
|
||
import type { RetrievedSnippet, ToolCallTrace } from '../../../../api';
|
||
import Markdown from '../../../../components/Markdown';
|
||
|
||
export function ReasoningView({ reasoning }: { reasoning: string }) {
|
||
return (
|
||
<Collapse
|
||
size="small"
|
||
ghost
|
||
items={[
|
||
{
|
||
key: 'reasoning',
|
||
label: <span style={{ fontSize: 12, color: 'var(--color-text-secondary)' }}>🧠 推理过程</span>,
|
||
children: (
|
||
<div style={{ fontSize: 12, color: 'var(--color-text-secondary)', lineHeight: 1.6, maxHeight: 240, overflow: 'auto' }}>
|
||
<Markdown>{reasoning}</Markdown>
|
||
</div>
|
||
)
|
||
}
|
||
]}
|
||
/>
|
||
);
|
||
}
|
||
|
||
export function RetrievedView({ retrieved }: { retrieved: RetrievedSnippet[] }) {
|
||
return (
|
||
<Collapse
|
||
size="small"
|
||
ghost
|
||
items={[
|
||
{
|
||
key: 'rag',
|
||
label: <span style={{ fontSize: 12, color: '#6366f1' }}>🔍 RAG 命中片段 ({retrieved.length})</span>,
|
||
children: (
|
||
<div style={{ fontSize: 12 }}>
|
||
{retrieved.map((r, i) => (
|
||
<div
|
||
key={i}
|
||
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)}
|
||
</div>
|
||
<div style={{ color: '#374151', whiteSpace: 'pre-wrap' }}>
|
||
{r.preview}
|
||
{r.preview.length >= 200 ? '…' : ''}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
)
|
||
}
|
||
]}
|
||
/>
|
||
);
|
||
}
|
||
|
||
export function ToolCallView({ calls, liveStyle }: { calls: ToolCallTrace[]; liveStyle?: boolean }) {
|
||
return (
|
||
<Collapse
|
||
size="small"
|
||
ghost
|
||
defaultActiveKey={liveStyle ? ['tc'] : undefined}
|
||
items={[
|
||
{
|
||
key: 'tc',
|
||
label: <span style={{ fontSize: 12, color: '#f97316' }}>🛠 工具调用 ({calls.length})</span>,
|
||
children: (
|
||
<div style={{ fontSize: 12 }}>
|
||
{calls.map((t, i) => {
|
||
const isPending = (t.result as any)?.pending;
|
||
const isFailed = t.result?.ok === false;
|
||
return (
|
||
<div
|
||
key={i}
|
||
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>}
|
||
{!isPending && t.result?.durationMs != null && <Tag>{t.result.durationMs}ms</Tag>}
|
||
{isFailed && <Tag color="error">失败</Tag>}
|
||
</div>
|
||
<div style={{ color: '#6b7280' }}>
|
||
<b>args:</b> {JSON.stringify(t.args)}
|
||
</div>
|
||
{!isPending && (
|
||
<div style={{ color: '#374151', marginTop: 4 }}>
|
||
<b>result:</b>{' '}
|
||
<code style={{ wordBreak: 'break-all' }}>
|
||
{JSON.stringify(t.result?.result ?? t.result?.error ?? t.result).slice(0, 500)}
|
||
</code>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
)
|
||
}
|
||
]}
|
||
/>
|
||
);
|
||
}
|