"use client" /** * status-footer.tsx — Thin status strip at the bottom of the home page * * The OLD home page made "is Tiger alive" the headline. The NEW home page * relegates it to a footer strip. When something IS wrong, the strip * promotes itself into a banner with a Restart button. */ import * as React from "react" import useSWR from "swr" import { cn } from "@/lib/utils" import { AlertCircle, RefreshCw, Loader2 } from "lucide-react" import { Button } from "@/components/ui/button" import { useBridgeRequest } from "@/hooks/use-bridge" interface TigerStatus { status: "online" | "degraded" | "offline" container: { status: string exitCode: number startedAt: string } openclaw: { running: boolean } system: { memoryUsagePct: number; memoryTotalMb: number } agent: { currentModel: string } } const fetcher = (url: string) => fetch(url).then((r) => r.json()) function uptimeShort(startedAt: string): string { if (!startedAt) return "—" const start = new Date(startedAt).getTime() const diff = Date.now() - start const m = Math.floor(diff / 60_000) if (m < 60) return `${m}m` const h = Math.floor(m / 60) if (h < 24) return `${h}h` const d = Math.floor(h / 24) return `${d}d` } function shortModel(m: string): string { if (!m) return "—" const parts = m.split("/") return parts[parts.length - 1].replace(/:.*$/, "") } export function StatusFooter() { const { data, error } = useSWR("/api/tiger/status", fetcher, { refreshInterval: 10_000, }) const { request } = useBridgeRequest() const [restarting, setRestarting] = React.useState(false) const isCrashed = data?.container?.exitCode === 255 const isOffline = error || data?.status === "offline" const handleRestart = async () => { setRestarting(true) try { await request("/api/tiger/restart", "POST") setTimeout(() => setRestarting(false), 3000) } catch (e) { console.error("Restart failed:", e) setRestarting(false) } } if (isCrashed) { return (
Tiger crashed (exit 255 — {shortModel(data?.agent?.currentModel || "")} unreachable)
) } if (isOffline) { return (
Bridge unreachable. Status data may be stale.
) } const dotClass = data?.status === "online" ? "bg-green-500" : data?.status === "degraded" ? "bg-amber-500" : "bg-zinc-500" return (
up {uptimeShort(data?.container?.startedAt || "")} {data?.system?.memoryUsagePct ?? 0}% mem {shortModel(data?.agent?.currentModel || "")} ₹— today
) }