import clsx from "clsx"; import React, { useEffect, useState, CSSProperties } from "react"; import { z } from "zod"; import { DashboardLayout } from "./DashboardLayout"; const agentSchema = z.object({ agent_id: z.string(), agent_name: z.string().nullable(), error: z.string().nullable(), external_llamacpp_addr: z.string(), is_authorized: z.boolean(), last_update: z.object({ nanos_since_epoch: z.number(), secs_since_epoch: z.number(), }), quarantined_until: z .object({ nanos_since_epoch: z.number(), secs_since_epoch: z.number(), }) .nullable(), slots_idle: z.number(), slots_processing: z.number(), }); const agentsResponseSchema = z.object({ agents: z.array(agentSchema), }); // use zod just for the sake of integrity type Agent = z.infer; type AgentsResponse = z.infer; const TICK_MS = 500; function formatTimestamp(timestamp: number): string { return new Date(timestamp * 1000).toLocaleString(); } export function Dashboard() { const [agents, setAgents] = useState([]); const [isError, setIsError] = useState(false); const [isFirstLoad, setIsFirstLoad] = useState(true); const [currentTick, setCurrentTick] = useState(0); useEffect( function () { const intervalId = setInterval(function () { setCurrentTick(function (previousTick) { return previousTick + 1; }); }, TICK_MS); return function () { clearInterval(intervalId); }; }, [setCurrentTick], ); useEffect( function () { const abortController = new AbortController(); fetch("/api/v1/agents", { signal: abortController.signal, }) .then((response) => response.json()) .then((agents) => agentsResponseSchema.parse(agents)) .then(function (agentsResponse: AgentsResponse) { setIsError(false); setAgents(agentsResponse.agents); }) .catch(function (error) { setIsError(true); console.error(error); }) .finally(function () { setIsFirstLoad(false); }); return function () { // abort controller prevents overlapping requests abortController.abort(); }; }, [ // fetch new data every tick currentTick, setAgents, setIsError, setIsFirstLoad, ], ); if (isError) { return (

Error while fetching current agents from the management server. Is it running?

Will automatically retry in a sec...

); } if (isFirstLoad) { return (

Loading agents...

); } if (agents.length < 1) { return (

Paddler 🏓

Registered Agents

No agents registered yet.

If you have an agent running, please wait a few seconds for it to register itself.

); } return (

Paddler 🏓

Registered Agents

{agents.map(function (agent: Agent) { const hasIssues = agent.error || !agent.is_authorized || agent.quarantined_until; return ( ); })}
Name Issues Llama.cpp address Last update Idle slots Processing slots
{agent.agent_name} {agent.error && ( <>

Error

{agent.error}

)} {!agent.is_authorized && ( <>

Unauthorized

Probably llama.cpp API key is either invalid or not present. Pass it to the agent with `--llamacpp-api-key=YOURKEY` flag.

)} {agent.quarantined_until && ( <>

Quarantined until{" "} {formatTimestamp( agent.quarantined_until.secs_since_epoch, )}

)} {!hasIssues &&

None

}
{agent.external_llamacpp_addr} {formatTimestamp(agent.last_update.secs_since_epoch)} {agent.slots_idle} {agent.slots_processing}
); }