112 lines
4.7 KiB
TypeScript
112 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { useMemo, useState } from "react";
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Select } from "@/components/ui/select";
|
|
import type { FleetAgent } from "@/lib/types";
|
|
|
|
export function AgentsClient({ agents }: { agents: FleetAgent[] }) {
|
|
const [query, setQuery] = useState("");
|
|
const [family, setFamily] = useState("");
|
|
|
|
const filteredAgents = useMemo(() => {
|
|
return agents.filter((agent) => {
|
|
const matchesQuery =
|
|
query.length === 0 ||
|
|
agent.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
agent.host.toLowerCase().includes(query.toLowerCase()) ||
|
|
agent.role.toLowerCase().includes(query.toLowerCase());
|
|
const matchesFamily = family.length === 0 || agent.family === family;
|
|
return matchesQuery && matchesFamily;
|
|
});
|
|
}, [agents, family, query]);
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Configured Agent Runtimes</CardTitle>
|
|
<CardDescription>
|
|
OpenClaw swarm members and ZeroClaw host runtimes are shown from the deployed fleet model.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="grid gap-3 md:grid-cols-[1fr_220px]">
|
|
<Input placeholder="Search by name, host, or role" value={query} onChange={(event) => setQuery(event.target.value)} />
|
|
<Select value={family} onChange={(event) => setFamily(event.target.value)}>
|
|
<option value="">All families</option>
|
|
<option value="openclaw">OpenClaw</option>
|
|
<option value="zeroclaw">ZeroClaw</option>
|
|
</Select>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<div className="grid gap-4 lg:grid-cols-2">
|
|
{filteredAgents.map((agent) => (
|
|
<Card key={agent.slug}>
|
|
<CardHeader>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<span>{agent.emoji}</span>
|
|
<span>{agent.name}</span>
|
|
</CardTitle>
|
|
<CardDescription>{agent.role}</CardDescription>
|
|
</div>
|
|
<div className="flex gap-2">
|
|
<Badge variant={agent.family === "openclaw" ? "default" : "success"}>{agent.family}</Badge>
|
|
<Badge variant="secondary">{agent.status}</Badge>
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<dl className="grid gap-2 text-sm text-slate-300 md:grid-cols-2">
|
|
<div>
|
|
<dt className="text-xs uppercase tracking-[0.2em] text-slate-500">Host</dt>
|
|
<dd>{agent.host}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="text-xs uppercase tracking-[0.2em] text-slate-500">Model</dt>
|
|
<dd>{agent.model || "Host-local/runtime-defined"}</dd>
|
|
</div>
|
|
<div className="md:col-span-2">
|
|
<dt className="text-xs uppercase tracking-[0.2em] text-slate-500">Runtime</dt>
|
|
<dd className="font-mono text-xs text-cyan-100">{agent.runtimePath}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="text-xs uppercase tracking-[0.2em] text-slate-500">Workload</dt>
|
|
<dd>{agent.workload} active</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="text-xs uppercase tracking-[0.2em] text-slate-500">Current task</dt>
|
|
<dd>{agent.currentTask || "No heartbeat task"}</dd>
|
|
</div>
|
|
</dl>
|
|
|
|
<div>
|
|
<p className="mb-2 text-xs uppercase tracking-[0.2em] text-slate-500">Channels</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{agent.channels.map((channel) => (
|
|
<Badge key={`${agent.slug}-${channel.label}`} variant="outline">
|
|
{channel.label}: {channel.value}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<p className="mb-2 text-xs uppercase tracking-[0.2em] text-slate-500">Tools</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{agent.tools.length ? agent.tools.map((tool) => <Badge key={tool} variant="secondary">{tool}</Badge>) : <span className="text-sm text-slate-400">No parsed tools.</span>}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|