import type { AgentLogEntry } from "@fusion/core"; import { useTranslation } from "react-i18next"; import type { TFunction } from "i18next"; import { ProviderIcon } from "./ProviderIcon"; import React, { useRef, useEffect, useState, useCallback, useLayoutEffect, useMemo, useId, type ReactElement } from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import type { Components } from "react-markdown"; import { Maximize2, Minimize2, Loader2, ChevronDown, ChevronRight } from "lucide-react"; import "./AgentLogViewer.css"; import { linkifyFilePaths, linkifyReactChildren } from "../utils/filePathLinkify"; import { getRelativeTimeBucket } from "../utils/relativeTimeAgo"; const MARKDOWN_TOGGLE_STORAGE_KEY = "fn-agent-log-markdown"; const TOOL_OUTPUT_TOGGLE_STORAGE_KEY = "fn-agent-log-tool-output"; function readBooleanPref(key: string, defaultValue: boolean): boolean { if (typeof window === "undefined") return defaultValue; try { const raw = window.localStorage.getItem(key); if (raw === null) return defaultValue; return raw === "true"; } catch { return defaultValue; } } function writeBooleanPref(key: string, value: boolean): void { if (typeof window === "undefined") return; try { window.localStorage.setItem(key, value ? "true" : "false"); } catch { // ignore storage failures (quota, private mode, etc.) } } /* FNXC:AgentLogTimestamps 2026-06-17-17:34: FN-6601 centralizes timestamp bucket math but AgentLog keeps its existing translation keys and future timestamps continue to render as "just now". */ function formatTimestamp(iso: string, t: TFunction<"app">): string { const bucket = getRelativeTimeBucket(iso); if (!bucket) { const date = new Date(iso); return Number.isFinite(date.getTime()) ? t("agentLog.timeJustNow", "just now") : date.toLocaleDateString(); } switch (bucket.bucket) { case "just-now": return t("agentLog.timeJustNow", "just now"); case "minutes": return t("agentLog.timeMinutesAgo", "{{count}}m ago", { count: bucket.count }); case "hours": return t("agentLog.timeHoursAgo", "{{count}}h ago", { count: bucket.count }); case "days": return t("agentLog.timeDaysAgo", "{{count}}d ago", { count: bucket.count }); case "weeks": case "older": return bucket.date.toLocaleDateString(); } } export const markdownComponents: Components = { p: ({ children, ...props }) =>
{linkifyReactChildren(children)}
, li: ({ children, ...props }) =>{children};
}
return {linkedChildren};
},
pre: ({ children, ...props }) => (
{children}
),
table: ({ children, ...props }) => (
{linkifyFilePaths(detail)}
{linkifyFilePaths(groupedText)}
)}
{linkifyFilePaths(groupedText)}
)}