SPB Git

spb/autoscholar

Public
4.6 KB · 107 lines tsx
1import { listWorkers, workerTelemetry } from "@autoscholar/core";2import { StatusBadge } from "@/components/StatusBadge";3import { ago, fmtBytes, fmtDateTime } from "@/lib/format";4import { db } from "@/lib/server/db";5import { WorkerActions } from "./WorkerActions";67export const dynamic = "force-dynamic";89export default async function MacLustrPage() {10  const d = db();11  const workers = await listWorkers(d);12  const tele = await Promise.all(workers.map((w) => workerTelemetry(d, w.id, 20)));13  return (14    <div className="space-y-6">15      <header>16        <p className="eyebrow">Compute</p>17        <h1 className="title-2 mt-1">MacLustr workers</h1>18        <p className="muted mt-1 text-sm">19          Authenticated worker telemetry. Workers connect outbound over the private network; nothing here is20          exposed publicly.21        </p>22      </header>23      {workers.length === 0 && (24        <div className="surface p-8 text-center">25          <p className="serif text-lg">No worker enrolled.</p>26          <p className="muted mt-1 text-sm">27            Install the worker daemon on a MacLustr node with the enrollment secret (docs/OPERATIONS.md). It28            appears here after its first heartbeat.29          </p>30        </div>31      )}32      {workers.map((w, i) => {33        const nm = (w.nodeMeta ?? {}) as Record<string, unknown>;34        const hb = tele[i] ?? [];35        const last = hb[0]?.load as Record<string, number> | undefined;36        return (37          <section key={w.id} className="surface p-4" aria-labelledby={`w-${w.id}`}>38            <div className="flex flex-wrap items-start justify-between gap-3">39              <div>40                <h2 id={`w-${w.id}`} className="title-3">41                  {w.name} <StatusBadge status={w.status} />42                </h2>43                <p className="muted text-xs">44                  worker {w.version ?? "?"} · protocol {w.protocolVersion} · enrolled{" "}45                  {fmtDateTime(w.enrolledAt)} · heartbeat {ago(w.lastHeartbeatAt)}46                  {w.quarantineReason ? ` · quarantined: ${w.quarantineReason}` : ""}47                </p>48              </div>49              <WorkerActions id={w.id} status={w.status} draining={!!w.drainRequested} />50            </div>51            <dl className="mt-3 grid grid-cols-2 gap-x-6 gap-y-1 text-xs sm:grid-cols-4">52              <dt className="muted">Running / capacity</dt>53              <dd>54                {w.running} / {w.capacity}55              </dd>56              <dt className="muted">Machine</dt>57              <dd className="font-mono">58                {String(nm.arch ?? "?")} · {String(nm.cpuCores ?? "?")} cores ·{" "}59                {nm.memoryBytes ? fmtBytes(Number(nm.memoryBytes)) : "?"}60              </dd>61              <dt className="muted">OS / user</dt>62              <dd className="font-mono">63                {String(nm.osVersion ?? "?")} · {String(nm.user ?? "?")}64              </dd>65              <dt className="muted">Sandbox</dt>66              <dd>67                {nm.sandboxAvailable ? (68                  <span style={{ color: "var(--color-ok-500)" }}>available (required for dispatch)</span>69                ) : (70                  <span style={{ color: "var(--color-danger-500)" }}>unavailable — no jobs dispatched</span>71                )}72              </dd>73              <dt className="muted">Profiles</dt>74              <dd className="font-mono">{w.profiles.join(", ")}</dd>75              <dt className="muted">SDK</dt>76              <dd className="font-mono">{String(nm.sdkVersion ?? "?")}</dd>77              <dt className="muted">Load / free mem / free disk</dt>78              <dd className="font-mono">79                {last80                  ? `${last.load1?.toFixed?.(2) ?? "?"} · ${last.memFreeBytes ? fmtBytes(last.memFreeBytes) : "?"} · ${last.diskFreeBytes ? fmtBytes(last.diskFreeBytes) : "?"}`81                  : "—"}82              </dd>83              <dt className="muted">Tools</dt>84              <dd className="font-mono">85                {nm.tools && typeof nm.tools === "object"86                  ? Object.entries(nm.tools as Record<string, string>)87                      .map(([k, v]) => `${k} ${v}`)88                      .join(" · ")89                  : "—"}90              </dd>91            </dl>92            {hb.length > 1 && (93              <p className="subtle mt-2 text-xs">94                Last {hb.length} heartbeats:{" "}95                {hb96                  .map((h) => `${(h.load as { load1?: number }).load1?.toFixed?.(1) ?? "?"}`)97                  .reverse()98                  .join(" ")}99              </p>100            )}101          </section>102        );103      })}104    </div>105  );106}107
Files · main
Menu

Theme