"use client"; import { formatDistanceToNow } from "date-fns"; import Link from "next/link"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { ResponsiveTable, ResponsiveTableCardList, ResponsiveTableCard, ResponsiveTableCardRow, } from "@/components/ui/responsive-table"; import { Skeleton } from "@/components/ui/skeleton"; import { HelpTip } from "@/components/ui/help-tip"; import { GitBranch, GitPullRequest, ExternalLink, CheckCircle2, XCircle, Clock, GitCommit, } from "lucide-react"; import type { WorkSessionSummary, WorkSessionStatus } from "@/types"; interface WorkSessionTableProps { sessions: WorkSessionSummary[] | undefined; isLoading: boolean; } // Mirrors the status hints in work-session-filters.tsx's dropdown — grounded // in roboco/services/work_session.py's transition triggers. const STATUS_HINTS: Record = { active: "An agent is currently working this branch.", completed: "The session's PR was merged — the branch's work is done.", abandoned: "Superseded by a re-claim, cancellation, or project deletion — never an auto-timeout.", }; function getStatusBadge(status: WorkSessionStatus) { switch (status) { case "active": return ( Active ); case "completed": return ( Completed ); case "abandoned": return ( Abandoned ); default: return {status}; } } function StatusBadge({ status }: { status: WorkSessionStatus }) { return ( {getStatusBadge(status)} ); } function PrBadge({ hasPr }: { hasPr: boolean }) { return hasPr ? ( PR Open ) : ( No PR ); } export function WorkSessionTable({ sessions, isLoading, }: WorkSessionTableProps) { if (isLoading) { return (
{Array.from({ length: 5 }).map((_, i) => ( ))}
); } if (!sessions || sessions.length === 0) { return (

No work sessions found

Work sessions are created when agents start working on tasks

); } return ( Branch Task Status PR Started Actions {sessions.map((session) => (
{session.branch_name}
{session.task_id.slice(0, 8)}... {formatDistanceToNow(new Date(session.started_at), { addSuffix: true, })} Open the owning task
))}
} cards={ {sessions.map((session) => (
{session.branch_name}
Open the owning task
{session.task_id.slice(0, 8)}... {formatDistanceToNow(new Date(session.started_at), { addSuffix: true, })}
))}
} /> ); }