import { Box, Paper, Stack, Text } from "@mantine/core"; import { IconCurrencyDollar, IconHistory, IconHourglass, IconStack2, } from "@tabler/icons-react"; import { mergeProjectedTurns, turnPresentation } from "../../state.js"; import { turnReportedWorkView, turnUsageMetricsView } from "../presentation"; import type { Task, TaskTurn } from "../types"; import { useEffect, useState } from "react"; import { RelativeTime } from "./RelativeTime"; import { LinkedText } from "./LinkedText"; import { ShimmerText } from "./ShimmerText"; import { StatCell, StaticStat, StatsGrid } from "./StatsGrid"; import { StatusBadge } from "./StatusBadge"; export function ActivityTimeline({ highlightTurnRef, task }: { highlightTurnRef: string | null; task: Task }) { const turns = mergeProjectedTurns(task, []) as Task["turns"]; if (!turns?.length) return No turn history has been recorded.; return ( {[...turns].reverse().map((turn, index) => { const presentation = turnPresentation(turn); const identity = turn.turnRef ?? turn.turnId ?? `turn-${index}`; const highlighted = identity === highlightTurnRef; const usage = turnUsageMetricsView(task, turn); return ( {presentation.sourceLabel} Request Result {presentation.status === "working" ? {presentation.summary} : } } label="Turn update time" value={presentation.updatedAt} /> } title="Tokens" value={usage.tokens.value} /> } title="Estimated cost" value={usage.cost.value} /> {usage.note && {usage.note}} ); })} ); } function TurnReportedWork({ turn }: { turn: TaskTurn }) { const now = useLiveNow(turn.result === null); const elapsed = turnReportedWorkView(turn, now); return ( } title="Duration" value={elapsed.value} /> ); } function useLiveNow(active: boolean) { const [now, setNow] = useState(() => Date.now()); useEffect(() => { if (!active) return undefined; setNow(Date.now()); const interval = window.setInterval(() => setNow(Date.now()), 1_000); return () => window.clearInterval(interval); }, [active]); return now; }