"use client"; import React from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { motion } from "framer-motion"; import { Avatar, Box, IconButton, Paper, Stack, Typography, alpha, useTheme, } from "@mui/material"; import AutoAwesome from "@mui/icons-material/AutoAwesome"; import ErrorOutlineRounded from "@mui/icons-material/ErrorOutlineRounded"; import VolumeUpRounded from "@mui/icons-material/VolumeUpRounded"; import PauseRounded from "@mui/icons-material/PauseRounded"; import PlayArrowRounded from "@mui/icons-material/PlayArrowRounded"; import StopRounded from "@mui/icons-material/StopRounded"; import { AgentArtifactPanel } from "./AgentArtifactPanel"; import { AgentProgressTimeline } from "./AgentProgressTimeline"; import { ChatInlineChart } from "./ChatInlineChart"; import type { ChatChartSeries } from "./ChatInlineChart"; import { ChatToolCallBlock } from "./ChatToolCallBlock"; import { parseAssistantMessageSections, parseContentWithToolCalls, type ContentSegment, } from "./chatMessageSections"; import markdownStyles from "./GlobalChatboxMarkdown.module.css"; import type { Message, SpeechState } from "./GlobalChatbox.types"; import { stripMarkdown } from "./GlobalChatbox.utils"; type AgentTurnProps = { message: Message; messageSpeechState: SpeechState; onSpeak: (messageId: string, text: string) => void; onPause: () => void; onResume: () => void; onStopSpeech: () => void; isTtsSupported: boolean; }; const MarkdownBlock = ({ children }: { children: string }) => (
{children}
); export const AgentTurn = React.memo( ({ message, messageSpeechState, onSpeak, onPause, onResume, onStopSpeech, isTtsSupported, }: AgentTurnProps) => { const theme = useTheme(); const isUser = message.role === "user"; const isErrorMessage = Boolean(message.isError); const parsedAssistantSections = !isUser && !isErrorMessage ? parseAssistantMessageSections(message.content) : null; const answerContent = parsedAssistantSections?.answer ?? message.content; const contentSegments: ContentSegment[] = !isUser && !isErrorMessage ? parseContentWithToolCalls(answerContent).segments : [{ type: "text", content: answerContent }]; if (isUser) { return ( {message.content} ); } return ( {isErrorMessage ? ( ) : ( )} {message.progress?.length && !isErrorMessage ? ( ) : null} {!isErrorMessage ? ( 回答 ) : null} {contentSegments.map((segment, segIdx) => { if (segment.type === "text") { const text = segment.content.trim(); if (!text && contentSegments.length > 1) return null; return {text || "..."}; } if (segment.type === "tool_call") { if ( segment.toolCall.tool === "chart" || segment.toolCall.tool === "show_chart" ) { const p = segment.toolCall.params; return ( ); } return ( ); } if (segment.type === "tool_call_pending") { return ( 正在准备工具调用... ); } return null; })} {message.artifacts?.length ? ( ) : null} {!isErrorMessage && isTtsSupported ? ( {messageSpeechState === "idle" ? ( onSpeak(message.id, stripMarkdown(answerContent))} aria-label="朗读消息" sx={{ color: "text.secondary", opacity: 0.68, p: 0.5 }} > ) : null} {messageSpeechState === "playing" ? ( <> ) : null} {messageSpeechState === "paused" ? ( <> ) : null} ) : null} ); }, ); AgentTurn.displayName = "AgentTurn";