Adopt design comps: dark system, new landing/auth, dashboard shell + canvas
Re-skins the whole app to the dark design comps and wires the new surfaces to
the backend (the /api proxy + auth + schemas are unchanged).
Design system:
- globals.css: remapped @theme tokens to the comp palette (#08080a base, coral
#ff6f61, status cyan/green/amber/purple/teal); token names preserved
- MeshMark: triangle + 3-node brand glyph; cm-flow/cm-blink/cm-halo keyframes
- marketing flipped light → dark
Backend (migration 0012):
- agents.model_binding (persisted on team deploy) + GET /api/claws/{id}/runtime-config
- routine_runs table + scheduler journaling + GET /api/routines/runs
- GET /api/claws/{id}/compartments (anatomy aggregate)
- GET /api/structure/stats (workspace counts)
Frontend:
- Landing: full dark marketing page (hero constellation, deploy ladder,
12-topology taxonomy, recursive execution, compare/Pareto, safety, self-host)
- Auth: dark split-panel AuthShell + comp LoginForm + Clerk SignIn themed dark
- Dashboard shell: TopBar (breadcrumb + live stats + deploy + user) + StatusBar
(runner/sandbox/doors); rail slimmed to 60px + 252px context column
- ConstellationCanvas (radial recursive) replaces the graph view in StructureCanvas;
selecting a claw opens ComputerPanel (apps/now-running/dock); RoutinesPanel
- Claw anatomy view (/claws/[id]/anatomy) from compartments + runtime-config
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3eca4ed70c
commit
540c74f42e
@@ -0,0 +1,129 @@
|
||||
"use client";
|
||||
|
||||
// The claw "anatomy" view (design comp, CLAW tier): a central core surrounded by
|
||||
// compartment cards — Skills / Personality / Memory / Tools·Doors / Capabilities
|
||||
// / Safety·§15 — aggregated from the backend. Each compartment is color-tinted.
|
||||
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
|
||||
interface Compartment {
|
||||
key: string;
|
||||
label: string;
|
||||
items: string[];
|
||||
count: number | null;
|
||||
}
|
||||
interface RuntimeConfig {
|
||||
model: string | null;
|
||||
sandbox_enabled: boolean;
|
||||
network_allowed: boolean;
|
||||
}
|
||||
|
||||
const TINT: Record<string, string> = {
|
||||
skills: "#ff6f61",
|
||||
personality: "#c98af0",
|
||||
memory: "#5fd08a",
|
||||
tools: "#5ec8d8",
|
||||
capabilities: "#e8b465",
|
||||
safety: "#6fd0c0",
|
||||
};
|
||||
|
||||
export function ClawAnatomy({ clawId }: { clawId: string }) {
|
||||
const [compartments, setCompartments] = useState<Compartment[]>([]);
|
||||
const [cfg, setCfg] = useState<RuntimeConfig | null>(null);
|
||||
const [name, setName] = useState("Claw");
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let live = true;
|
||||
void (async () => {
|
||||
const [c, rc, settings] = await Promise.all([
|
||||
fetch(`/api/claws/${clawId}/compartments`).then((x) => (x.ok ? x.json() : [])).catch(() => []),
|
||||
fetch(`/api/claws/${clawId}/runtime-config`).then((x) => (x.ok ? x.json() : null)).catch(() => null),
|
||||
fetch(`/api/claws/settings/full?clawId=${clawId}`).then((x) => (x.ok ? x.json() : null)).catch(() => null),
|
||||
]);
|
||||
if (!live) return;
|
||||
setCompartments(c as Compartment[]);
|
||||
setCfg(rc as RuntimeConfig | null);
|
||||
const n = (settings as { agent?: { name?: string } } | null)?.agent?.name;
|
||||
if (n) setName(n);
|
||||
setLoaded(true);
|
||||
})();
|
||||
return () => {
|
||||
live = false;
|
||||
};
|
||||
}, [clawId]);
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex w-full max-w-4xl flex-col gap-6 p-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link
|
||||
href={`/claws/${clawId}`}
|
||||
className="flex items-center gap-1.5 font-mono text-[11px] text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<ArrowLeft size={13} /> back to chat
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Core */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div
|
||||
className="relative flex size-[72px] items-center justify-center rounded-full text-2xl font-bold"
|
||||
style={{ background: "linear-gradient(135deg,#ff9a6a,#ff6f4a)", color: "#2a0d05" }}
|
||||
>
|
||||
<span className="cm-halo absolute inset-0 rounded-full" style={{ background: "rgba(255,111,97,.3)" }} />
|
||||
<span className="relative">{name.charAt(0).toUpperCase()}</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-xl font-semibold tracking-tight">{name}</h1>
|
||||
<p className="font-mono text-[11px] text-muted-foreground">
|
||||
ANATOMY · what {name} is made of
|
||||
{cfg?.model ? <span className="ml-2 capitalize text-running">● {cfg.model}</span> : null}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Compartments */}
|
||||
{!loaded ? (
|
||||
<p className="text-sm text-muted-foreground">Loading…</p>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{compartments.map((c) => {
|
||||
const tint = TINT[c.key] ?? "#ff6f61";
|
||||
return (
|
||||
<div
|
||||
key={c.key}
|
||||
className="rounded-2xl border bg-[#0c0c0f] p-4"
|
||||
style={{ borderColor: `${tint}40` }}
|
||||
>
|
||||
<div className="mb-2.5 flex items-center justify-between">
|
||||
<span className="font-mono text-[10px] tracking-[0.12em]" style={{ color: tint }}>
|
||||
{c.label.toUpperCase()}
|
||||
</span>
|
||||
{c.count != null ? (
|
||||
<span className="font-mono text-[10px] text-muted-foreground">{c.count}</span>
|
||||
) : null}
|
||||
</div>
|
||||
{c.items.length === 0 ? (
|
||||
<p className="text-xs text-subtle-foreground">—</p>
|
||||
) : (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
{c.items.slice(0, 5).map((it, i) => (
|
||||
<div key={i} className="truncate text-[13px] text-[#cfcfd5]">
|
||||
{it}
|
||||
</div>
|
||||
))}
|
||||
{c.items.length > 5 ? (
|
||||
<div className="text-xs text-subtle-foreground">+{c.items.length - 5} more</div>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user