"use client"; import { Activity, BarChart3, Database, History, LineChart, MonitorCog } from "lucide-react"; import { AnimatePresence, MotionConfig, motion } from "motion/react"; import type { ReactNode } from "react"; import { cn } from "@/lib/utils"; import { normalizeSafeChartData, parseChartSpec, type SafeChartData, type SafeChartSeries, type SafeChartSpec } from "../chart-data"; import type { AgentUiResult } from "../types"; import type { UIEnvelope } from "../ui-envelope"; import { agentLayoutTransition, agentPanelItemVariants, agentPanelListVariants } from "./agent-motion"; type AgentUiEnvelopeRendererProps = { results: AgentUiResult[]; }; export function AgentUiEnvelopeRenderer({ results }: AgentUiEnvelopeRendererProps) { if (results.length === 0) { return null; } return ( {results.map((result) => ( ))} ); } function AgentUiResultCard({ result }: { result: AgentUiResult }) { const { envelope } = result; return (
{getEnvelopeIcon(envelope)}

{getEnvelopeTitle(envelope)}

{getSurfaceLabel(envelope.surface)}

agent-ui@1
{envelope.kind === "chart" ? : null} {envelope.kind === "registered_component" ? : null} {envelope.kind === "map_action" ? null : null}
); } function SafeChartEnvelope({ envelope }: { envelope: Extract }) { const spec = parseChartSpec(envelope.spec); const data = normalizeSafeChartData(envelope.data); if (!data || data.series.length === 0 || data.xData.length === 0) { return ; } return (

{spec.title ?? "Agent 图表"}

{spec.chartType === "bar" ? "柱状图" : "折线图"} {spec.yAxisName ? ` · ${spec.yAxisName}` : ""}

{data.series.slice(0, 3).map((series, index) => ( {series.name} ))}
{spec.xAxisName ?

{spec.xAxisName}

: null}
); } function SafeChartSvg({ spec, data }: { spec: SafeChartSpec; data: SafeChartData }) { const width = 360; const height = 190; const padding = { top: 16, right: 18, bottom: 32, left: 38 }; const plotWidth = width - padding.left - padding.right; const plotHeight = height - padding.top - padding.bottom; const values = data.series.flatMap((series) => series.data); const min = Math.min(0, ...values); const max = Math.max(...values); const range = max - min || 1; const xFor = (index: number) => padding.left + (data.xData.length === 1 ? plotWidth / 2 : (index / (data.xData.length - 1)) * plotWidth); const yFor = (value: number) => padding.top + plotHeight - ((value - min) / range) * plotHeight; const ticks = createTicks(min, max); return ( {ticks.map((tick) => { const y = yFor(tick); return ( {formatChartNumber(tick)} ); })} {data.xData.map((label, index) => ( {shortLabel(label)} ))} {data.series.slice(0, 4).map((series, seriesIndex) => (series.type ?? spec.chartType) === "bar" ? ( ) : ( ) )} ); } function LineSeries({ series, seriesIndex, xFor, yFor }: { series: SafeChartSeries; seriesIndex: number; xFor: (index: number) => number; yFor: (value: number) => number; }) { const points = series.data.map((value, index) => `${xFor(index)},${yFor(value)}`).join(" "); const stroke = chartStroke(seriesIndex); return ( {series.data.map((value, index) => ( ))} ); } function BarSeries({ series, seriesIndex, seriesCount, xFor, yFor, baselineY }: { series: SafeChartSeries; seriesIndex: number; seriesCount: number; xFor: (index: number) => number; yFor: (value: number) => number; baselineY: number; }) { const fill = chartStroke(seriesIndex); const barWidth = Math.max(5, 22 / seriesCount); const offset = (seriesIndex - (seriesCount - 1) / 2) * (barWidth + 2); return ( {series.data.map((value, index) => { const y = yFor(value); return ( ); })} ); } function RegisteredComponentEnvelope({ envelope }: { envelope: Extract; }) { if (envelope.component === "HistoryPanel") { return ( ); } if (envelope.component === "ScadaPanel") { return ( ); } return ; } function TrustedPanelShell({ icon, title, children }: { icon: ReactNode; title: string; children: ReactNode; }) { return (
{icon} {title}
{children}
); } function PropRows({ props, labels }: { props: unknown; labels: Record }) { const rows = safePropRows(props, labels); if (rows.length === 0) { return

已打开可信面板,暂无可展示参数。

; } return (
{rows.map((row) => (
{row.label}
{row.value}
))}
); } function FallbackText({ text }: { text: string }) { return (
{text}
); } function safePropRows(props: unknown, labels: Record) { if (!isRecord(props)) { return []; } return Object.entries(labels).flatMap(([key, label]) => { const value = props[key]; if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") { return []; } return [{ label, value: String(value) }]; }); } function getEnvelopeIcon(envelope: UIEnvelope) { if (envelope.kind === "chart") { return envelope.spec && isRecord(envelope.spec) && envelope.spec.chart_type === "bar" ? (