78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
import { ClickableCard } from "@astryxdesign/core/ClickableCard";
|
|
import { Icon } from "@astryxdesign/core/Icon";
|
|
import { HStack, StackItem, VStack } from "@astryxdesign/core/Layout";
|
|
import { Section } from "@astryxdesign/core/Section";
|
|
import { Heading, Text } from "@astryxdesign/core/Text";
|
|
import { IconActivityHeartbeat } from "@tabler/icons-react";
|
|
import { backendLabel, modelLabel } from "../lib/backend-label";
|
|
import { styles, type AgentRow } from "../lib/agent-rows";
|
|
import { ActiveTasks } from "./ActiveTasks";
|
|
import { ActivityChart } from "./ActivityChart";
|
|
import { AgentAvatar } from "./AgentAvatar";
|
|
import { AgentStatusLabel } from "./AgentStatusLabel";
|
|
import { BackendLogo } from "./BackendLogo";
|
|
|
|
function compactHeartbeat(value: string) {
|
|
if (value === "Never") return "—";
|
|
const match = value.match(/^(\d+)\s+(second|minute|hour)/);
|
|
if (!match) return value;
|
|
const unit = match[2] === "second" ? "s" : match[2] === "minute" ? "m" : "h";
|
|
return `${match[1]}${unit}`;
|
|
}
|
|
|
|
export function AgentCard({ agent }: { agent: AgentRow }) {
|
|
return (
|
|
<ClickableCard
|
|
label={`Open ${agent.name}`}
|
|
href={`/agents/${agent.id}/overview`}
|
|
padding={4}
|
|
xstyle={styles.agentCard}
|
|
>
|
|
<VStack gap={3} xstyle={styles.cardContent}>
|
|
<HStack gap={3} vAlign="center">
|
|
<AgentAvatar agent={agent} />
|
|
<StackItem size="fill">
|
|
<VStack gap={0}>
|
|
<Heading level={3} maxLines={1}>
|
|
{agent.name}
|
|
</Heading>
|
|
<HStack gap={2} vAlign="center">
|
|
<BackendLogo backend={agent.backend} />
|
|
<Text type="supporting" color="secondary" maxLines={1}>
|
|
{backendLabel(agent.backend)}
|
|
</Text>
|
|
</HStack>
|
|
<Text type="supporting" size="sm" color="secondary" maxLines={1}>
|
|
{modelLabel(agent.modelOverride)}
|
|
</Text>
|
|
</VStack>
|
|
</StackItem>
|
|
<AgentStatusLabel agent={agent} />
|
|
</HStack>
|
|
|
|
<Text type="body" color="secondary" maxLines={1}>
|
|
{agent.description}
|
|
</Text>
|
|
|
|
<Section variant="muted" padding={3} xstyle={styles.activityPanel}>
|
|
<ActivityChart agent={agent} />
|
|
<HStack gap={4} hAlign="between" vAlign="center" xstyle={styles.activityContent}>
|
|
<HStack gap={1} vAlign="center">
|
|
<ActiveTasks agent={agent} metric />
|
|
<Text type="supporting" color="secondary">
|
|
Active tasks
|
|
</Text>
|
|
</HStack>
|
|
<HStack gap={1} vAlign="center">
|
|
<Icon icon={IconActivityHeartbeat} size="xsm" color="secondary" />
|
|
<Text type="large" weight="bold">
|
|
{compactHeartbeat(agent.lastHeartbeat)}
|
|
</Text>
|
|
</HStack>
|
|
</HStack>
|
|
</Section>
|
|
</VStack>
|
|
</ClickableCard>
|
|
);
|
|
}
|