import { useMemo } from "react"; import { Link } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import type { Issue } from "@paperclipai/shared"; import { heartbeatsApi, type LiveRunForIssue } from "../api/heartbeats"; import { issuesApi } from "../api/issues"; import type { TranscriptEntry } from "../adapters"; import { queryKeys } from "../lib/queryKeys"; import { cn, relativeTime } from "../lib/utils"; import { ExternalLink } from "lucide-react"; import { Identity } from "./Identity"; import { RunTranscriptView } from "./transcript/RunTranscriptView"; import { useLiveRunTranscripts } from "./transcript/useLiveRunTranscripts"; const MIN_DASHBOARD_RUNS = 4; function isRunActive(run: LiveRunForIssue): boolean { return run.status === "queued" || run.status === "running"; } interface ActiveAgentsPanelProps { companyId: string; } export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { const { data: liveRuns } = useQuery({ queryKey: [...queryKeys.liveRuns(companyId), "dashboard"], queryFn: () => heartbeatsApi.liveRunsForCompany(companyId, MIN_DASHBOARD_RUNS), }); const runs = liveRuns ?? []; const { data: issues } = useQuery({ queryKey: queryKeys.issues.list(companyId), queryFn: () => issuesApi.list(companyId), enabled: runs.length > 0, }); const issueById = useMemo(() => { const map = new Map(); for (const issue of issues ?? []) { map.set(issue.id, issue); } return map; }, [issues]); const { transcriptByRun, hasOutputForRun } = useLiveRunTranscripts({ runs, companyId, maxChunksPerRun: 120, }); return (

Agents

{runs.length === 0 ? (

No recent agent runs.

) : (
{runs.map((run) => ( ))}
)}
); } function AgentRunCard({ run, issue, transcript, hasOutput, isActive, }: { run: LiveRunForIssue; issue?: Issue; transcript: TranscriptEntry[]; hasOutput: boolean; isActive: boolean; }) { return (
{isActive ? ( ) : ( )}
{isActive ? "Live now" : run.finishedAt ? `Finished ${relativeTime(run.finishedAt)}` : `Started ${relativeTime(run.createdAt)}`}
{run.issueId && (
{issue?.identifier ?? run.issueId.slice(0, 8)} {issue?.title ? ` - ${issue.title}` : ""}
)}
); }