import React, { useEffect, useMemo, useState } from "react"; const DEFAULT_MEMORIES = [ { id: "mem-001", title: "Session continuity", type: "thread", updatedAt: "2026-04-16", importance: "high", summary: "Maintains governor-specific thread continuity and active context." }, { id: "mem-002", title: "Execution preference", type: "governance", updatedAt: "2026-04-16", importance: "high", summary: "AURA provides final closure before governed action is executed." } ]; const DEFAULT_MESSAGES = [ { id: "msg-001", role: "assistant", content: "I am AURA. This governor shell is active and ready. You can brief, inspect, or launch direct mode." } ]; function safeArray(v, fallback = []) { return Array.isArray(v) ? v : fallback; } function cx(...parts) { return parts.filter(Boolean).join(" "); } function makeThreadId(nodeKey) { const rand = Math.random().toString(36).slice(2, 8).toUpperCase(); return `${String(nodeKey || "NODE").toUpperCase()}-${rand}`; } function statusTone(status) { switch (status) { case "GOVERNED": case "READY": case "STABLE": return "bg-emerald-500/15 text-emerald-300 border-emerald-500/30"; case "DEGRADED": case "WATCH": return "bg-amber-500/15 text-amber-300 border-amber-500/30"; case "BLOCK": case "CRITICAL": return "bg-red-500/15 text-red-300 border-red-500/30"; default: return "bg-slate-500/15 text-slate-300 border-slate-500/30"; } } function governorTheme(nodeKey) { switch (nodeKey) { case "jupiter": return { accent: "text-cyan-300", border: "border-cyan-500/30", glow: "shadow-cyan-500/10" }; case "mars": return { accent: "text-rose-300", border: "border-rose-500/30", glow: "shadow-rose-500/10" }; case "neptune": return { accent: "text-indigo-300", border: "border-indigo-500/30", glow: "shadow-indigo-500/10" }; case "saturn": return { accent: "text-amber-300", border: "border-amber-500/30", glow: "shadow-amber-500/10" }; case "moon": return { accent: "text-violet-300", border: "border-violet-500/30", glow: "shadow-violet-500/10" }; case "sun": return { accent: "text-yellow-300", border: "border-yellow-500/30", glow: "shadow-yellow-500/10" }; case "earth": return { accent: "text-emerald-300", border: "border-emerald-500/30", glow: "shadow-emerald-500/10" }; case "pluto": return { accent: "text-fuchsia-300", border: "border-fuchsia-500/30", glow: "shadow-fuchsia-500/10" }; default: return { accent: "text-sky-300", border: "border-sky-500/30", glow: "shadow-sky-500/10" }; } } function DefaultDirectPanel({ node, metrics, onLaunchAction, threadId }) { const [command, setCommand] = useState(""); const [output, setOutput] = useState("Joker command input is live."); const [files, setFiles] = useState([]); const [status, setStatus] = useState("READY"); async function handleFiles(event) { const picked = Array.from(event.target.files || []); const loaded = []; for (const file of picked) { try { const text = await file.text(); loaded.push({ name: file.name, type: file.type || "application/octet-stream", size: file.size, text }); } catch (error) { loaded.push({ name: file.name, type: file.type || "application/octet-stream", size: file.size, text: "", error: String(error) }); } } setFiles(loaded); setOutput( JSON.stringify( { message: "Files loaded into Joker intake.", files: loaded.map((f) => ({ name: f.name, type: f.type, size: f.size })) }, null, 2 ) ); } async function send(action = "execute") { if (!String(command || "").trim() && files.length === 0) { setStatus("FAILED"); setOutput("No command or files provided."); return; } setStatus(action === "dry_run" ? "CONFIRM" : "EXECUTING"); const payload = { threadId, governor: node?.name || "JUPITER", identity: node?.auraName || "AURA", mode: "COMMAND", action, command, files, timestamp: new Date().toISOString() }; try { const res = await fetch("/api/command", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); const text = await res.text(); let data; try { data = JSON.parse(text); } catch { data = { raw: text }; } if (!res.ok) { setStatus("FAILED"); setOutput( JSON.stringify( { error: "Request failed", status: res.status, statusText: res.statusText, response: data }, null, 2 ) ); return; } setStatus(action === "dry_run" ? "CONFIRM" : "COMPLETE"); setOutput(JSON.stringify(data, null, 2)); } catch (error) { setStatus("FAILED"); setOutput( JSON.stringify( { error: String(error), hint: "Verify /api/command exists.", payload }, null, 2 ) ); } } async function copyOutput() { try { await navigator.clipboard.writeText(output); setStatus("COMPLETE"); } catch { setStatus("FAILED"); } } function downloadOutput() { const blob = new Blob([output], { type: "text/plain;charset=utf-8" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "joker-output.txt"; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); } function clearAll() { setCommand(""); setFiles([]); setStatus("READY"); setOutput("Cleared."); } return (
Command Input