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 "mars": 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 }) { return (
Live Metrics
{safeArray(metrics).map((m) => (
{m.label}
{m.value}
))}
Direct Actions
{safeArray(node.directActions).map((action) => ( ))}
); } function DefaultMemoryTable({ memories }) { return (
Memory Rail
{safeArray(memories).map((m) => ( ))}
Title Type Importance Updated
{m.title}
{m.summary}
{m.type} {m.importance} {m.updatedAt}
); } function DefaultChatPanel({ messages, input, setInput, onSend, threadId, nodeName, auraName }) { return (
{auraName} / {nodeName}
Thread ID: {threadId}
Chat First
{safeArray(messages).map((m) => (
{m.role === "assistant" ? auraName : "You"}
{m.content}
))}
setInput(e.target.value)} placeholder={`Speak to ${auraName} in ${nodeName} mode...`} className="flex-1 rounded-xl border border-white/10 bg-black/20 px-4 py-3 text-sm text-white outline-none placeholder:text-white/30" />
); } export default function NodeShell({ node = { key: "mars", name: "Mars", subtitle: "Capital Governor", auraName: "AURA", status: "READY", description: "Independent governor node with chat-first interaction, direct launch, memory continuity, and execution control.", briefing: "AURA is active in this governor. You can request a briefing, inspect the dashboard, or launch direct mode.", directActions: [ { key: "dashboard", label: "Open Dashboard", description: "Bypass chat and open the active governor dashboard." }, { key: "signals", label: "Show Signals", description: "Open current governed signal view." }, { key: "execution", label: "Execution Panel", description: "Open governed execution controls." } ] }, initialMessages = DEFAULT_MESSAGES, initialMemories = DEFAULT_MEMORIES, metrics = [ { label: "Admissibility", value: "0.74" }, { label: "Coherence", value: "0.81" }, { label: "Thread State", value: "Active" }, { label: "Execution", value: "Guarded" } ], renderDirectPanel, renderMemoryPanel, onLaunchAction, onSendMessage }) { const theme = useMemo(() => governorTheme(node.key), [node.key]); const [threadId] = useState(() => makeThreadId(node.key)); const [messages, setMessages] = useState(initialMessages); const [memories] = useState(initialMemories); const [input, setInput] = useState(""); const [mode, setMode] = useState("briefing"); useEffect(() => { setMessages(initialMessages); }, [initialMessages]); function handleLaunchAction(action) { if (action && action.key) { setMode(action.key); } if (typeof onLaunchAction === "function") { onLaunchAction({ action, node, threadId }); } } function handleSend() { const trimmed = String(input || "").trim(); if (!trimmed) return; const userMessage = { id: `user-${Date.now()}`, role: "user", content: trimmed }; const assistantMessage = { id: `assistant-${Date.now() + 1}`, role: "assistant", content: typeof onSendMessage === "function" ? onSendMessage({ text: trimmed, node, threadId, mode }) || `AURA received your request in ${node.name} mode.` : `AURA received your request in ${node.name} mode.` }; setMessages((prev) => [...prev, userMessage, assistantMessage]); setInput(""); } return (
{node.auraName || "AURA"} / {node.name}

{node.subtitle || node.name}

{node.description}

{node.status}
Thread: {threadId}
Mode: {mode}
Governor Briefing
{node.briefing}
System Strip
Governor
{node.name}
AURA Identity
{node.auraName || "AURA"}
Thread
{threadId}
Status
{node.status}
{mode === "memory" ? ( renderMemoryPanel ? ( renderMemoryPanel({ node, memories, threadId }) ) : ( ) ) : renderDirectPanel ? ( renderDirectPanel({ node, metrics, mode, threadId, onLaunchAction: handleLaunchAction }) ) : ( )}
); }