"use client"; // "Push to Hub": publish this claw's .brain (identity + skills + memory) to // ClawBrainHub under owner/name:version (POST /api/claws/{id}/brain/push). // Requires BRAINHUB_API_KEY on the server; surfaces a clear error if unset. import { useEffect, useState } from "react"; import { UploadCloud, X } from "lucide-react"; const mono = "'JetBrains Mono', ui-monospace, monospace"; export function PushBrainModal({ clawId, clawName, onClose }: { clawId: string; clawName: string; onClose: () => void }) { const slug = clawName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "agent"; const [reference, setReference] = useState(`me/${slug}:1.0.0`); const [description, setDescription] = useState(""); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const [done, setDone] = useState(false); useEffect(() => { const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); const canPush = /.+\/.+:.+/.test(reference.trim()) && !busy; async function push() { if (!canPush) { setError("Use owner/name:version, e.g. me/my-agent:1.0.0"); return; } setBusy(true); setError(null); try { const res = await fetch(`/api/claws/${clawId}/brain/push`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ reference: reference.trim(), description: description.trim(), tags: [] }), }); if (!res.ok) { setError(res.status === 400 ? "Push rejected — check the name, or BRAINHUB_API_KEY isn't set on the server." : `Push failed (${res.status})`); setBusy(false); return; } setDone(true); setBusy(false); } catch { setError("Network error"); setBusy(false); } } const field: React.CSSProperties = { width: "100%", boxSizing: "border-box", padding: "9px 11px", borderRadius: 9, border: "1px solid rgba(255,255,255,.12)", background: "#141417", color: "#eaeaee", fontSize: 13, fontFamily: mono }; return (
e.stopPropagation()} role="dialog" aria-modal="true" aria-label="Push to ClawBrainHub" style={{ width: "100%", maxWidth: 460, borderRadius: 16, background: "#0d0d10", border: "1px solid rgba(255,255,255,.1)", boxShadow: "0 30px 90px rgba(0,0,0,.6)", padding: 22, animation: "scale-in .18s ease" }}>
Push to ClawBrainHub
Publish {clawName}'s .brain as a versioned release.
{done ? (
Published {reference.trim()} to ClawBrainHub.
) : (
{error ?
{error}
: null}
)}
); }