"use client"; import { useCallback, useEffect, useRef } from "react"; import type { AgentLogEntry } from "@/lib/work-package-types"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Badge } from "@/components/ui/badge"; import { Download } from "lucide-react"; function levelTone(level: AgentLogEntry["level"]) { if (level === "success") return "text-emerald-700"; if (level === "warn") return "text-amber-700"; if (level === "error") return "text-rose-700"; return "text-foreground"; } function formatLogTime(value: string) { return value.slice(11, 19); } export function buildAgentLogExportText(args: { logs: AgentLogEntry[]; busy: boolean; }) { const { logs, busy } = args; const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19); const header = [ `Agent Log Export — ${timestamp}`, `Total entries: ${logs.length}`, `Status: ${busy ? "Running" : "Idle"}`, "", ]; const body = logs.map( (log) => `[${formatLogTime(log.createdAt)}] ${log.level.toUpperCase()} ${log.title}\n${log.detail}\n`, ); return [...header, ...body].join("\n"); } export function AgentLogPanel(props: { logs: AgentLogEntry[]; busy: boolean; }) { const { logs, busy } = props; const bottomRef = useRef(null); useEffect(() => { bottomRef.current?.scrollIntoView({ block: "end" }); }, [logs.length]); const exportLogs = useCallback(() => { const content = buildAgentLogExportText({ logs, busy }); const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19); const blob = new Blob([content], { type: "text/plain;charset=utf-8" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `agent-log-${timestamp}.txt`; a.click(); URL.revokeObjectURL(url); }, [logs, busy]); return (
Agent Log
Background activity, command routing, and board updates.
{busy ? "Running" : "Idle"}
{logs.length ? ( <> {logs.map((log) => (
{log.title}
{log.detail}
{formatLogTime(log.createdAt)}
))}
) : (
No agent activity yet.
)}
); }