import { useState } from "react"; import { useAppStore } from "../../store/useAppStore"; import { useAuditStore } from "../audit"; import { CardGrid, Notice, PageHeader, StatCard } from "../components"; import { Button, Surface, Tag } from "../../components/primitives"; import { Icon } from "../../components/Icon"; type Tab = "logs" | "trace" | "metrics" | "audit"; const TABS: ReadonlyArray<{ id: Tab; label: string }> = [ { id: "logs", label: "实时日志" }, { id: "trace", label: "Tracing" }, { id: "metrics", label: "指标" }, { id: "audit", label: "审计" }, ]; export function ObservabilityModule(): React.ReactNode { const [tab, setTab] = useState("logs"); const deviceUpdates = useAppStore((s) => s.deviceUpdates); const audit = useAuditStore((s) => s.records); const clearAudit = useAuditStore((s) => s.clear); return (
{TABS.map((t) => ( ))}
{tab === "logs" ? : null} {tab === "trace" ? : null} {tab === "metrics" ? : null} {tab === "audit" ? : null}
); } function LogsTail({ lines }: { lines: string[] }): React.ReactNode { return (

实时日志流(WS 事件回显)

tail
{lines.length === 0 ? ( 暂无实时事件。接入 /ws/chat 后,此处回显 stream / tool / device_update / reminder 等事件。 ) : (
          {lines.join("\n")}
        
)} 完整后端日志分级 tail / 过滤 / 导出需后端 M10+ 提供。
); } function TraceView(): React.ReactNode { return (

Tracing 视图

{["LLM 调用链", "工具链", "编排链"].map((x) => (
{x}
{x} 占位 —— 后端 M10+ 提供 span/trace 数据
))}
); } function MetricsView(): React.ReactNode { return (
} label="请求 QPS" value="—" sub="网关指标占位" tone="accent" /> } label="LLM 调用次数" value="—" sub="用量/费用占位" tone="neutral" /> } label="子代理事件" value="—" sub="编排指标占位" tone="ok" /> } label="工时/Token" value="—" sub="成本占位" tone="warn" /> 指标时序图 / 导出需后端 M10+ 提供。
); } interface AuditViewProps { records: ReturnType["records"]; onClear: () => void; } function AuditView({ records, onClear }: AuditViewProps): React.ReactNode { return (

审计日志(who / what / when / result)

管理 + 敏感操作全程落审计
{records.length === 0 ? ( 暂无审计记录。本面板的管理/敏感操作(策略写入、主人档案编辑、API key 签发等)都会在此登记。 ) : ( {records.map((r) => ( ))}
who what when result
{r.who} {r.what} {new Date(r.when).toLocaleString()} {r.result}
)}
); }