Spaces:
Paused
Paused
| import { useQuery } from "@tanstack/react-query"; | |
| import { Link } from "@/lib/router"; | |
| import { AGENT_ROLE_LABELS, type Agent, type AgentRuntimeState } from "@paperclipai/shared"; | |
| import { agentsApi } from "../api/agents"; | |
| import { useCompany } from "../context/CompanyContext"; | |
| import { getAdapterLabel } from "../adapters/adapter-display-registry"; | |
| import { queryKeys } from "../lib/queryKeys"; | |
| import { StatusBadge } from "./StatusBadge"; | |
| import { Identity } from "./Identity"; | |
| import { formatDate, agentUrl } from "../lib/utils"; | |
| import { Separator } from "@/components/ui/separator"; | |
| interface AgentPropertiesProps { | |
| agent: Agent; | |
| runtimeState?: AgentRuntimeState; | |
| } | |
| const roleLabels = AGENT_ROLE_LABELS as Record<string, string>; | |
| function PropertyRow({ label, children }: { label: string; children: React.ReactNode }) { | |
| return ( | |
| <div className="flex items-center gap-3 py-1.5"> | |
| <span className="text-xs text-muted-foreground shrink-0 w-20">{label}</span> | |
| <div className="flex items-center gap-1.5 min-w-0">{children}</div> | |
| </div> | |
| ); | |
| } | |
| export function AgentProperties({ agent, runtimeState }: AgentPropertiesProps) { | |
| const { selectedCompanyId } = useCompany(); | |
| const { data: agents } = useQuery({ | |
| queryKey: queryKeys.agents.list(selectedCompanyId!), | |
| queryFn: () => agentsApi.list(selectedCompanyId!), | |
| enabled: !!selectedCompanyId && !!agent.reportsTo, | |
| }); | |
| const reportsToAgent = agent.reportsTo ? agents?.find((a) => a.id === agent.reportsTo) : null; | |
| return ( | |
| <div className="space-y-4"> | |
| <div className="space-y-1"> | |
| <PropertyRow label="Status"> | |
| <StatusBadge status={agent.status} /> | |
| </PropertyRow> | |
| <PropertyRow label="Role"> | |
| <span className="text-sm">{roleLabels[agent.role] ?? agent.role}</span> | |
| </PropertyRow> | |
| {agent.title && ( | |
| <PropertyRow label="Title"> | |
| <span className="text-sm">{agent.title}</span> | |
| </PropertyRow> | |
| )} | |
| <PropertyRow label="Adapter"> | |
| <span className="text-sm font-mono">{getAdapterLabel(agent.adapterType)}</span> | |
| </PropertyRow> | |
| </div> | |
| <Separator /> | |
| <div className="space-y-1"> | |
| {(runtimeState?.sessionDisplayId ?? runtimeState?.sessionId) && ( | |
| <PropertyRow label="Session"> | |
| <span className="text-xs font-mono"> | |
| {String(runtimeState.sessionDisplayId ?? runtimeState.sessionId).slice(0, 12)}... | |
| </span> | |
| </PropertyRow> | |
| )} | |
| {runtimeState?.lastError && ( | |
| <PropertyRow label="Last error"> | |
| <span className="text-xs text-red-600 dark:text-red-400 truncate max-w-[160px]">{runtimeState.lastError}</span> | |
| </PropertyRow> | |
| )} | |
| {agent.lastHeartbeatAt && ( | |
| <PropertyRow label="Last Heartbeat"> | |
| <span className="text-sm">{formatDate(agent.lastHeartbeatAt)}</span> | |
| </PropertyRow> | |
| )} | |
| {agent.reportsTo && ( | |
| <PropertyRow label="Reports To"> | |
| {reportsToAgent ? ( | |
| <Link to={agentUrl(reportsToAgent)} className="hover:underline"> | |
| <Identity name={reportsToAgent.name} size="sm" /> | |
| </Link> | |
| ) : ( | |
| <span className="text-sm font-mono">{agent.reportsTo.slice(0, 8)}</span> | |
| )} | |
| </PropertyRow> | |
| )} | |
| <PropertyRow label="Created"> | |
| <span className="text-sm">{formatDate(agent.createdAt)}</span> | |
| </PropertyRow> | |
| </div> | |
| </div> | |
| ); | |
| } | |