File size: 2,706 Bytes
fed4f1f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Box, Stack, Typography } from '@mui/material';
import MarkdownContent from './MarkdownContent';
import ToolCallGroup from './ToolCallGroup';
import type { Message } from '@/types/agent';

interface AssistantMessageProps {
  message: Message;
  /** True when this message is actively receiving streaming chunks. */
  isStreaming?: boolean;
}

export default function AssistantMessage({ message, isStreaming = false }: AssistantMessageProps) {
  const renderSegments = () => {
    if (message.segments && message.segments.length > 0) {
      // Find the index of the last text segment (that's the one being streamed)
      let lastTextIdx = -1;
      for (let i = message.segments.length - 1; i >= 0; i--) {
        if (message.segments[i].type === 'text') {
          lastTextIdx = i;
          break;
        }
      }

      return message.segments.map((segment, idx) => {
        if (segment.type === 'text' && segment.content) {
          return (
            <MarkdownContent
              key={idx}
              content={segment.content}
              isStreaming={isStreaming && idx === lastTextIdx}
            />
          );
        }
        if (segment.type === 'tools' && segment.tools && segment.tools.length > 0) {
          return <ToolCallGroup key={idx} tools={segment.tools} />;
        }
        return null;
      });
    }

    // Fallback: render raw content
    if (message.content) {
      return <MarkdownContent content={message.content} isStreaming={isStreaming} />;
    }

    return null;
  };

  return (
    <Box sx={{ minWidth: 0 }}>
      {/* Role label + timestamp */}
      <Stack direction="row" alignItems="baseline" spacing={1} sx={{ mb: 0.5 }}>
        <Typography
          variant="caption"
          sx={{
            fontWeight: 700,
            fontSize: '0.72rem',
            color: 'var(--muted-text)',
            textTransform: 'uppercase',
            letterSpacing: '0.04em',
          }}
        >
          Assistant
        </Typography>
        <Typography
          variant="caption"
          sx={{
            fontSize: '0.66rem',
            color: 'var(--muted-text)',
            opacity: 0.6,
          }}
        >
          {new Date(message.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
        </Typography>
      </Stack>

      {/* Message bubble */}
      <Box
        sx={{
          maxWidth: { xs: '95%', md: '85%' },
          bgcolor: 'var(--surface)',
          borderRadius: 1.5,
          borderTopLeftRadius: 4,
          px: { xs: 1.5, md: 2.5 },
          py: 1.5,
          border: '1px solid var(--border)',
        }}
      >
        {renderSegments()}
      </Box>
    </Box>
  );
}