"use client"; import Image from "next/image"; import React from "react"; import { AnimatePresence, motion } from "framer-motion"; import { Box, Paper, Stack, Typography, alpha, useTheme, Grid } from "@mui/material"; import WaterDropRounded from "@mui/icons-material/WaterDropRounded"; import SensorsRounded from "@mui/icons-material/SensorsRounded"; import TroubleshootRounded from "@mui/icons-material/TroubleshootRounded"; import MapRounded from "@mui/icons-material/MapRounded"; import { AgentTurn } from "./AgentTurn"; import { TypingIndicator } from "./GlobalChatbox.parts"; import type { BranchGroup, BranchTransition, Message, SpeechState, } from "./GlobalChatbox.types"; type AgentWorkspaceProps = { messages: Message[]; branchGroups: BranchGroup[]; branchTransition: BranchTransition | null; isStreaming: boolean; bottomRef: React.RefObject; speakingMessageId: string | null; speechState: SpeechState; onSpeak: (messageId: string, text: string) => void; onPauseSpeech: () => void; onResumeSpeech: () => void; onStopSpeech: () => void; isTtsSupported: boolean; onRegenerate: () => void; onEditResubmit: (messageId: string, newContent: string) => void; onCycleBranch: (rootMessageId: string, direction: -1 | 1) => void; }; const EmptyState = () => { const theme = useTheme(); const capabilities = [ { icon: , label: "水力瓶颈识别" }, { icon: , label: "异常状态预警" }, { icon: , label: "调度与改造建议" }, { icon: , label: "GIS 地图联动" }, ]; return ( TJWater Agent 我已就绪,请描述任务 你可以使用自然语言下达指令,我会自主规划决策执行、并在地图上呈现分析结果。 {capabilities.map((item) => ( {item.icon} {item.label} ))} ); }; export const AgentWorkspace = ({ messages, branchGroups, branchTransition, isStreaming, bottomRef, speakingMessageId, speechState, onSpeak, onPauseSpeech, onResumeSpeech, onStopSpeech, isTtsSupported, onRegenerate, onEditResubmit, onCycleBranch, }: AgentWorkspaceProps) => { const theme = useTheme(); const latestAssistant = [...messages] .reverse() .find((message) => message.role === "assistant"); const showTypingIndicator = isStreaming && (!latestAssistant || (latestAssistant.content.trim().length === 0 && !(latestAssistant.artifacts?.length))); const stableMessages = branchTransition ? messages.slice(0, branchTransition.parentCount) : messages; const transitionMessages = branchTransition ? messages.slice(branchTransition.parentCount) : []; const renderTurn = (message: Message) => { const rootMessageId = message.branchRootId ?? message.id; const branchGroup = branchGroups.find( (group) => group.rootMessageId === rootMessageId, ); return ( 1 ? { activeIndex: branchGroup.activeIndex, total: branchGroup.branches.length, } : undefined } messageSpeechState={speakingMessageId === message.id ? speechState : "idle"} onSpeak={onSpeak} onPause={onPauseSpeech} onResume={onResumeSpeech} onStopSpeech={onStopSpeech} isTtsSupported={isTtsSupported} onRegenerate={onRegenerate} onEditResubmit={onEditResubmit} onCycleBranch={onCycleBranch} /> ); }; return ( {messages.length === 0 ? : null} {messages.length > 0 ? ( {stableMessages.map(renderTurn)} {branchTransition ? ( {transitionMessages.map(renderTurn)} ) : null} ) : null} {showTypingIndicator ? ( ) : null}
); };