68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import React from 'react';
|
|
|
|
import { cn } from '@/lib/utils';
|
|
import { Badge } from '@/components/UI';
|
|
|
|
import type { DebugTranscriptTextRow } from './types';
|
|
|
|
const roleLabelMap: Record<DebugTranscriptTextRow['role'], string> = {
|
|
user: 'Me',
|
|
assistant: 'AI',
|
|
notice: 'Debug',
|
|
};
|
|
|
|
const MessageText: React.FC<{
|
|
row: DebugTranscriptTextRow;
|
|
}> = ({ row }) => {
|
|
if (row.role === 'notice') {
|
|
return (
|
|
<div className="flex justify-start">
|
|
<div className="max-w-full rounded-md border border-white/10 bg-black/25 px-3 py-2 text-[11px] text-muted-foreground">
|
|
<div className="mb-1 flex items-center gap-2">
|
|
<span className="uppercase tracking-[0.14em] opacity-70">{roleLabelMap[row.role]}</span>
|
|
</div>
|
|
<div className="whitespace-pre-wrap break-words">{row.text}</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const isUser = row.role === 'user';
|
|
|
|
return (
|
|
<div className={cn('flex', isUser ? 'justify-end' : 'justify-start')}>
|
|
<div
|
|
className={cn(
|
|
'max-w-[85%] rounded-lg px-3 py-2 text-sm',
|
|
isUser
|
|
? 'bg-primary text-primary-foreground'
|
|
: 'bg-card border border-white/10 shadow-sm text-foreground'
|
|
)}
|
|
>
|
|
<div className="mb-1 flex flex-wrap items-center gap-1.5">
|
|
<span className="text-[10px] uppercase tracking-wider opacity-70">
|
|
{roleLabelMap[row.role]}
|
|
</span>
|
|
{row.role === 'assistant' &&
|
|
typeof row.ttfbMs === 'number' &&
|
|
Number.isFinite(row.ttfbMs) && (
|
|
<Badge
|
|
variant="outline"
|
|
className="border-cyan-300/40 bg-cyan-500/10 px-1.5 py-0.5 text-[10px] text-cyan-200"
|
|
>
|
|
TTFB {Math.round(row.ttfbMs)}ms
|
|
</Badge>
|
|
)}
|
|
{row.role === 'assistant' && row.isStreaming && (
|
|
<span className="inline-flex h-2 w-2 animate-pulse rounded-full bg-primary/80" />
|
|
)}
|
|
</div>
|
|
<div className="whitespace-pre-wrap break-words">{row.text}</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default React.memo(MessageText);
|
|
|