agentic-os/interface/hq-dashboard/app/page.jsx

812 lines
46 KiB
JavaScript

"use client";
import React, { useState, useEffect, useRef } from "react";
import {
Activity,
Terminal,
User,
Cpu,
ShieldAlert,
CheckCircle,
XCircle,
Database,
FileText,
Sparkles,
Send,
RefreshCw,
Play,
GitPullRequest,
Layers,
Settings,
AlertCircle,
Trash2,
HeartPulse,
LogOut,
Maximize2
} from "lucide-react";
export default function Page() {
const [activeTab, setActiveTab] = useState("dashboard");
// Claw Chat State
const [messages, setMessages] = useState([
{
role: "assistant",
content: "Hello! I am Claw, your local agent. I have access to your Kubernetes namespace and Proxmox cluster nodes. How can I help you today?",
timestamp: "Just now"
}
]);
const [inputValue, setInputValue] = useState("");
const [isClawTyping, setIsClawTyping] = useState(false);
const [clawTerminalLogs, setClawTerminalLogs] = useState([]);
// OpsAgent State
const [pendingApprovals, setPendingApprovals] = useState([
{
id: "ops-req-102",
targetType: "proxmox",
targetId: "102",
action: "clean_disk",
details: "LXC container root filesystem is at 94% disk usage. Recommending apt cache clean and temporary file removal.",
timestamp: "5 mins ago",
status: "pending"
},
{
id: "ops-req-201",
targetType: "kubernetes",
targetId: "curio-app-xyz",
action: "restart_pod",
details: "Pod curio-app-xyz is in CrashLoopBackOff state. Logs indicate: 'Database connection failed: Connection refused by 10.96.20.10:5432'. Recommending pod deletion to trigger k8s reschedule.",
timestamp: "10 mins ago",
status: "pending"
}
]);
const [opsLogs, setOpsLogs] = useState([
"2026-05-29 01:10:00 [OpsAgent] Initialized diagnostic run on K8s cluster...",
"2026-05-29 01:10:15 [OpsAgent] Found Pod 'curio-app-xyz' in CrashLoopBackOff. Emitting warning.",
"2026-05-29 01:12:02 [OpsAgent] Proxmox VMID 102 root usage checked: 94%. Action required."
]);
// Curio HMS State
const [dictationText, setDictationText] = useState(
"Patient is a 45-year-old male presenting with severe, crushing chest pain radiating to his left arm. He has a past medical history of hypertension. Admitting to Cardiac ICU."
);
const [clinicalNote, setClinicalNote] = useState(null);
const [billingCodes, setBillingCodes] = useState([]);
const [isProcessingClinical, setIsProcessingClinical] = useState(false);
// Workflow logs state
const [workflows, setWorkflows] = useState([
{ id: "wf-bernard-001", name: "PRReviewWorkflow", agent: "Bernard", target: "pr-401", status: "completed", result: "Approved with suggestions" },
{ id: "wf-gumbo-002", name: "GumboSummarizeWorkflow", agent: "Gumbo", target: "api-spec.md", status: "completed", result: "Summary persisted in PG" },
{ id: "wf-ops-003", name: "OpsRemediateWorkflow", agent: "OpsAgent", target: "VMID 102", status: "running", result: "Awaiting approval signal" }
]);
const messagesEndRef = useRef(null);
const terminalEndRef = useRef(null);
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages, isClawTyping]);
useEffect(() => {
terminalEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [clawTerminalLogs]);
// Simulated Claw response logic
const handleSendMessage = async (e) => {
e.preventDefault();
if (!inputValue.trim()) return;
const userText = inputValue;
setMessages(prev => [...prev, { role: "user", content: userText, timestamp: "Just now" }]);
setInputValue("");
setIsClawTyping(true);
setClawTerminalLogs(prev => [...prev, `[Claw] Received instruction: "${userText}"`]);
// Parse commands for visual interactions
let responseText = "";
let logs = [];
await new Promise(resolve => setTimeout(resolve, 1500));
const cleanInput = userText.toLowerCase();
if (cleanInput.includes("pod") || cleanInput.includes("k8s") || cleanInput.includes("kubectl")) {
logs = [
"Connecting to Kubernetes API server...",
"Executing: kubectl get pods -n default",
"Found 2 pods in namespace 'default':",
" - web-pod-xyz 0/1 CrashLoopBackOff 5 2h",
" - db-pod-abc 1/1 Running 0 5d",
"Fetching logs for 'web-pod-xyz'...",
" Error detected: Database connection refused by 10.96.20.10:5432"
];
responseText = "I've checked the Kubernetes pods. Pod `web-pod-xyz` is currently failing due to a database connection refusal. You can use the **OpsAgent** tab to approve a pod restart or scale the DB deployment.";
} else if (cleanInput.includes("proxmox") || cleanInput.includes("vmid") || cleanInput.includes("disk")) {
logs = [
"Establishing SSH connection to Proxmox cluster host 192.168.8.225...",
"Running: pct status 102",
" status: running",
"Running: pct exec 102 -- df -h /",
" Filesystem Size Used Avail Use% Mounted on",
" /dev/loop0 20G 19G 0.2G 94% /",
"Disk usage critically high! Proposed action: clean_disk"
];
responseText = "Proxmox Container ID `102` is running out of disk space (94% used). I have created a pending action under the **OpsAgent Center** to perform automated cleanup. Would you like me to execute it?";
} else if (cleanInput.includes("hello") || cleanInput.includes("hi")) {
responseText = "Hi there! I am Claw, your local personal assistant. Try asking me to `check k8s pods` or `diagnose proxmox container 102`.";
} else {
responseText = `I've analyzed your query: "${userText}". I recommend initiating an **OpsRemediateWorkflow** to check the status or scanning your configuration files. Let me know if you would like me to trigger that for you.`;
}
setClawTerminalLogs(prev => [...prev, ...logs, "[Claw] Response formulated successfully."]);
setMessages(prev => [...prev, { role: "assistant", content: responseText, timestamp: "Just now" }]);
setIsClawTyping(false);
};
// Approval Handlers
const handleApprove = async (id, action, target) => {
setPendingApprovals(prev => prev.map(item => item.id === id ? { ...item, status: "approved" } : item));
setOpsLogs(prev => [...prev, `2026-05-29 01:14:10 [OpsAgent] RECEIVED APPROVAL SIGNAL for request ${id}`]);
// Simulate execution log
let execLogs = [
`[OpsAgent] Initiating execution of '${action}' on target '${target}'...`,
`[OpsAgent] Sending signal to Temporal workflow...`,
];
if (action === "clean_disk") {
execLogs.push(
"[OpsAgent] SSH into Proxmox node VMID 102...",
"[OpsAgent] running: apt-get clean && rm -rf /tmp/*",
"[OpsAgent] Disk space cleared. Root filesystem usage reduced from 94% to 71%."
);
} else {
execLogs.push(
`[OpsAgent] Running: kubectl delete pod ${target} -n default`,
`[OpsAgent] Pod deleted. K8s controller successfully scheduled a replica.`
);
}
// Delay log write to simulate real execution
for (const log of execLogs) {
await new Promise(resolve => setTimeout(resolve, 800));
setOpsLogs(prev => [...prev, log]);
}
setPendingApprovals(prev => prev.filter(item => item.id !== id));
setWorkflows(prev => prev.map(wf => wf.target === (action === "clean_disk" ? "VMID 102" : target) ? { ...wf, status: "completed", result: "Remediated successfully" } : wf));
};
const handleReject = (id) => {
setPendingApprovals(prev => prev.filter(item => item.id !== id));
setOpsLogs(prev => [...prev, `2026-05-29 01:14:30 [OpsAgent] Request ${id} REJECTED by operator. Action aborted.`]);
};
// Clinical note simulation
const handleProcessClinical = async () => {
setIsProcessingClinical(true);
setClinicalNote(null);
setBillingCodes([]);
await new Promise(resolve => setTimeout(resolve, 1500));
setClinicalNote({
subjective: "Patient is a 45-year-old male presenting with severe, crushing chest pain radiating to his left arm. He reports shortness of breath.",
objective: "Alert and oriented. Reports pain scale 8/10.",
assessment: "Acute Myocardial Infarction suspected.",
plan: "Order EKG, troponin levels. Administer Aspirin 324mg immediately. Admit to Cardiac ICU."
});
setBillingCodes([
{ code: "I21.9", desc: "Acute myocardial infarction, unspecified" },
{ code: "93000", desc: "Electrocardiogram, tracing and report" },
{ code: "99223", desc: "Initial hospital care, high level severity" }
]);
setIsProcessingClinical(false);
};
return (
<div className="app-container">
{/* Sidebar Navigation */}
<aside className="sidebar">
<div style={{ display: "flex", flexDirection: "column", gap: "32px" }}>
{/* Dashboard Title */}
<div style={{ display: "flex", alignItems: "center", gap: "10px", padding: "0 8px" }}>
<div style={{ width: "32px", height: "32px", borderRadius: "8px", background: "linear-gradient(135deg, var(--accent-violet), var(--accent-cyan))", display: "flex", alignItems: "center", justifyContent: "center" }}>
<Terminal size={18} style={{ color: "#fff" }} />
</div>
<div>
<h2 style={{ fontSize: "16px", color: "var(--text-primary)" }}>Agentic OS</h2>
<span style={{ fontSize: "11px", color: "var(--text-muted)", letterSpacing: "1px", textTransform: "uppercase" }}>Control HQ</span>
</div>
</div>
{/* Nav Items */}
<nav style={{ display: "flex", flexDirection: "column", gap: "6px" }}>
<button
onClick={() => setActiveTab("dashboard")}
style={{
display: "flex", alignItems: "center", gap: "12px", width: "100%", padding: "12px 16px", border: "none", borderRadius: "8px", cursor: "pointer",
background: activeTab === "dashboard" ? "rgba(139, 92, 246, 0.15)" : "transparent",
color: activeTab === "dashboard" ? "var(--accent-violet)" : "var(--text-secondary)",
fontWeight: activeTab === "dashboard" ? "600" : "500",
transition: "all 0.2s"
}}
>
<Cpu size={18} />
Dashboard Home
</button>
<button
onClick={() => setActiveTab("claw")}
style={{
display: "flex", alignItems: "center", gap: "12px", width: "100%", padding: "12px 16px", border: "none", borderRadius: "8px", cursor: "pointer",
background: activeTab === "claw" ? "rgba(6, 182, 212, 0.15)" : "transparent",
color: activeTab === "claw" ? "var(--accent-cyan)" : "var(--text-secondary)",
fontWeight: activeTab === "claw" ? "600" : "500",
transition: "all 0.2s"
}}
>
<Sparkles size={18} />
Claw Assistant
</button>
<button
onClick={() => setActiveTab("ops")}
style={{
display: "flex", alignItems: "center", gap: "12px", width: "100%", padding: "12px 16px", border: "none", borderRadius: "8px", cursor: "pointer",
background: activeTab === "ops" ? "rgba(245, 158, 11, 0.15)" : "transparent",
color: activeTab === "ops" ? "var(--accent-amber)" : "var(--text-secondary)",
fontWeight: activeTab === "ops" ? "600" : "500",
transition: "all 0.2s"
}}
>
<ShieldAlert size={18} />
OpsAgent Center
{pendingApprovals.length > 0 && (
<span style={{ fontSize: "10px", padding: "2px 6px", borderRadius: "10px", background: "var(--accent-amber)", color: "#000", fontWeight: "700", marginLeft: "auto" }}>
{pendingApprovals.length}
</span>
)}
</button>
<button
onClick={() => setActiveTab("curio")}
style={{
display: "flex", alignItems: "center", gap: "12px", width: "100%", padding: "12px 16px", border: "none", borderRadius: "8px", cursor: "pointer",
background: activeTab === "curio" ? "rgba(16, 185, 129, 0.15)" : "transparent",
color: activeTab === "curio" ? "var(--accent-emerald)" : "var(--text-secondary)",
fontWeight: activeTab === "curio" ? "600" : "500",
transition: "all 0.2s"
}}
>
<HeartPulse size={18} />
Clinical Workspace
</button>
<button
onClick={() => setActiveTab("logs")}
style={{
display: "flex", alignItems: "center", gap: "12px", width: "100%", padding: "12px 16px", border: "none", borderRadius: "8px", cursor: "pointer",
background: activeTab === "logs" ? "rgba(255, 255, 255, 0.05)" : "transparent",
color: activeTab === "logs" ? "var(--text-primary)" : "var(--text-secondary)",
fontWeight: activeTab === "logs" ? "600" : "500",
transition: "all 0.2s"
}}
>
<Layers size={18} />
Workflows & Logs
</button>
</nav>
</div>
{/* Footer info */}
<div style={{ display: "flex", flexDirection: "column", gap: "8px", borderTop: "1px solid var(--border-color)", paddingTop: "16px" }}>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<span style={{ width: "8px", height: "8px", borderRadius: "50%" }} className="pulse-emerald"></span>
<span style={{ fontSize: "12px", color: "var(--text-secondary)" }}>Temporal Worker Connected</span>
</div>
<span style={{ fontSize: "11px", color: "var(--text-muted)" }}>v1.2.0-Production</span>
</div>
</aside>
{/* Main Content Area */}
<main className="main-content">
<header className="header">
<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
<h1 style={{ fontSize: "18px", textTransform: "capitalize" }}>{activeTab.replace("curio", "Clinical Curio").replace("ops", "OpsAgent Hub")}</h1>
<div style={{ fontSize: "12px", color: "var(--text-muted)", padding: "2px 8px", background: "rgba(255,255,255,0.05)", borderRadius: "4px" }}>
Namespace: ai-agents
</div>
</div>
<div style={{ display: "flex", alignItems: "center", gap: "16px" }}>
<div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end" }}>
<span style={{ fontSize: "12px", color: "var(--text-primary)" }}>Sysadmin Console</span>
<span style={{ fontSize: "10px", color: "var(--accent-cyan)" }}>192.168.8.250</span>
</div>
<div style={{ width: "36px", height: "36px", borderRadius: "50%", background: "#1f293d", display: "flex", alignItems: "center", justifyContent: "center" }}>
<User size={18} style={{ color: "var(--text-secondary)" }} />
</div>
</div>
</header>
<div className="content-body">
{/* TAB 1: DASHBOARD HOME */}
{activeTab === "dashboard" && (
<div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
{/* Stat Cards */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: "20px" }}>
<div className="glass glass-interactive" style={{ padding: "20px" }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "12px" }}>
<span style={{ color: "var(--text-secondary)", fontSize: "14px" }}>Total Active Agents</span>
<Cpu style={{ color: "var(--accent-violet)" }} size={20} />
</div>
<h2 style={{ fontSize: "28px" }}>5 / 8</h2>
<div style={{ fontSize: "12px", color: "var(--text-muted)", marginTop: "6px" }}>Active in namespace</div>
</div>
<div className="glass glass-interactive" style={{ padding: "20px" }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "12px" }}>
<span style={{ color: "var(--text-secondary)", fontSize: "14px" }}>Temporal Workflows</span>
<RefreshCw style={{ color: "var(--accent-cyan)" }} size={20} />
</div>
<h2 style={{ fontSize: "28px" }}>12 Active</h2>
<div style={{ fontSize: "12px", color: "var(--text-emerald)", marginTop: "6px" }}>98.8% success SLA</div>
</div>
<div className="glass glass-interactive" style={{ padding: "20px" }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "12px" }}>
<span style={{ color: "var(--text-secondary)", fontSize: "14px" }}>Diagnostic Logs</span>
<Database style={{ color: "var(--accent-emerald)" }} size={20} />
</div>
<h2 style={{ fontSize: "28px" }}>142 MB</h2>
<div style={{ fontSize: "12px", color: "var(--text-muted)", marginTop: "6px" }}>Persisted in PostgreSQL</div>
</div>
<div className="glass glass-interactive" style={{ padding: "20px" }}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "12px" }}>
<span style={{ color: "var(--text-secondary)", fontSize: "14px" }}>Action Approvals</span>
<ShieldAlert style={{ color: "var(--accent-amber)" }} size={20} />
</div>
<h2 style={{ fontSize: "28px", color: "var(--accent-amber)" }}>{pendingApprovals.length} Awaiting</h2>
<div style={{ fontSize: "12px", color: "var(--accent-rose)", marginTop: "6px" }}>Require administrator override</div>
</div>
</div>
{/* Agent Status Panel */}
<div className="glass" style={{ padding: "24px" }}>
<h3 style={{ fontSize: "16px", marginBottom: "16px" }}>Core Agent Ecosystem Status</h3>
<div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
{[
{ name: "Bernard", role: "GitOps Reviewer & Workflow Monitor", status: "Idle", desc: "Awaiting PR push events on Gitea hooks.", type: "system" },
{ name: "Gumbo", role: "Documentation Summarizer", status: "Active", desc: "Indexing recent technical wiki docs via MCP filesystem.", type: "assistant" },
{ name: "OpsAgent", role: "SRE Diagnostics & Self-Healing", status: "Pending approval", desc: "Awaiting administrator decision for remediation action.", type: "remediator" },
{ name: "Claw", role: "Local Assistant CLI (OpenClaw clone)", status: "Active", desc: "Awaiting operator prompt input.", type: "assistant" },
{ name: "Curio Billing/Triage", role: "HMS AI Assist", status: "Idle", desc: "Standing by for clinical intake recording inputs.", type: "clinical" },
].map((agent, i) => (
<div key={i} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "rgba(255,255,255,0.01)" }}>
<div>
<h4 style={{ fontSize: "14px", fontWeight: "600" }}>{agent.name}</h4>
<p style={{ fontSize: "12px", color: "var(--text-secondary)" }}>{agent.role} — <span style={{ color: "var(--text-muted)" }}>{agent.desc}</span></p>
</div>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<span style={{ width: "8px", height: "8px", borderRadius: "50%" }} className={agent.status.includes("Pending") ? "pulse-amber" : "pulse-emerald"}></span>
<span style={{ fontSize: "12px", fontWeight: "600", color: agent.status.includes("Pending") ? "var(--accent-amber)" : "var(--text-secondary)" }}>{agent.status}</span>
</div>
</div>
))}
</div>
</div>
{/* Quick Trigger Block */}
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "20px" }}>
<div className="glass" style={{ padding: "20px" }}>
<h3 style={{ fontSize: "14px", marginBottom: "12px" }}>Diagnostics & Ops Triggers</h3>
<div style={{ display: "flex", gap: "10px" }}>
<button
onClick={() => {
setActiveTab("ops");
}}
style={{ padding: "10px 16px", border: "none", borderRadius: "6px", background: "linear-gradient(135deg, var(--accent-amber), #d97706)", color: "#000", fontWeight: "600", cursor: "pointer", display: "flex", alignItems: "center", gap: "8px" }}
>
<ShieldAlert size={16} />
Go to Approval Center
</button>
<button
onClick={() => {
setActiveTab("claw");
setMessages(prev => [...prev, { role: "assistant", content: "I am ready. Tell me to `check k8s pods` to test system diagnostic logic.", timestamp: "Just now" }]);
}}
style={{ padding: "10px 16px", border: "1px solid var(--border-color)", borderRadius: "6px", background: "rgba(255,255,255,0.05)", color: "var(--text-primary)", fontWeight: "600", cursor: "pointer" }}
>
Diagnose Pods
</button>
</div>
</div>
<div className="glass" style={{ padding: "20px" }}>
<h3 style={{ fontSize: "14px", marginBottom: "12px" }}>Knowledge Intake Trigger</h3>
<div style={{ display: "flex", gap: "10px" }}>
<button
onClick={() => {
alert("Triggered GumboSummarizeWorkflow for api-spec.md");
}}
style={{ padding: "10px 16px", border: "none", borderRadius: "6px", background: "linear-gradient(135deg, var(--accent-violet), var(--accent-cyan))", color: "#fff", fontWeight: "600", cursor: "pointer", display: "flex", alignItems: "center", gap: "8px" }}
>
<Sparkles size={16} />
Summarize Documentation (Gumbo)
</button>
</div>
</div>
</div>
</div>
)}
{/* TAB 2: CLAW PERSONAL ASSISTANT */}
{activeTab === "claw" && (
<div className="fade-in" style={{ display: "grid", gridTemplateColumns: "1fr 340px", gap: "24px", height: "calc(100vh - 140px)", overflow: "hidden" }}>
{/* Chat Panel */}
<div className="glass" style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }}>
{/* Chat Header */}
<div style={{ padding: "16px 24px", borderBottom: "1px solid var(--border-color)", display: "flex", alignItems: "center", gap: "12px", background: "rgba(255,255,255,0.01)" }}>
<div style={{ width: "10px", height: "10px", borderRadius: "50%" }} className="pulse-emerald"></div>
<div>
<h3 style={{ fontSize: "15px" }}>Claw Personal Assistant</h3>
<span style={{ fontSize: "11px", color: "var(--text-muted)" }}>Runs locally. Accesses file tools & system terminal.</span>
</div>
</div>
{/* Chat Messages */}
<div style={{ flex: 1, padding: "24px", overflowY: "auto", display: "flex", flexDirection: "column", gap: "16px" }}>
{messages.map((msg, i) => (
<div
key={i}
style={{
display: "flex",
flexDirection: "column",
alignItems: msg.role === "user" ? "flex-end" : "flex-start",
maxWidth: "85%",
alignSelf: msg.role === "user" ? "flex-end" : "flex-start"
}}
>
<div
style={{
padding: "12px 16px",
borderRadius: "12px",
fontSize: "14px",
lineHeight: "1.5",
background: msg.role === "user" ? "var(--accent-cyan)" : "rgba(255, 255, 255, 0.04)",
color: msg.role === "user" ? "#000" : "var(--text-primary)",
border: msg.role === "user" ? "none" : "1px solid var(--border-color)"
}}
>
{msg.content}
</div>
<span style={{ fontSize: "10px", color: "var(--text-muted)", marginTop: "4px", padding: "0 4px" }}>{msg.timestamp}</span>
</div>
))}
{isClawTyping && (
<div style={{ alignSelf: "flex-start", display: "flex", alignItems: "center", gap: "4px", padding: "12px 16px", background: "rgba(255, 255, 255, 0.04)", borderRadius: "12px", border: "1px solid var(--border-color)" }}>
<span style={{ width: "6px", height: "6px", background: "var(--text-secondary)", borderRadius: "50%", display: "inline-block", animation: "bounce 1.4s infinite ease-in-out both" }}></span>
<span style={{ width: "6px", height: "6px", background: "var(--text-secondary)", borderRadius: "50%", display: "inline-block", animation: "bounce 1.4s infinite ease-in-out both 0.2s" }}></span>
<span style={{ width: "6px", height: "6px", background: "var(--text-secondary)", borderRadius: "50%", display: "inline-block", animation: "bounce 1.4s infinite ease-in-out both 0.4s" }}></span>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Chat Input */}
<form onSubmit={handleSendMessage} style={{ padding: "20px", borderTop: "1px solid var(--border-color)", display: "flex", gap: "10px", background: "rgba(8,10,16,0.3)" }}>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Ask Claw: e.g. 'check pods' or 'check disk VMID 102'..."
style={{ flex: 1, padding: "12px 16px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "var(--bg-secondary)", color: "var(--text-primary)", outline: "none", fontSize: "14px" }}
/>
<button
type="submit"
style={{ padding: "12px 20px", border: "none", borderRadius: "8px", background: "var(--accent-cyan)", color: "#000", fontWeight: "600", cursor: "pointer", display: "flex", alignItems: "center", gap: "8px" }}
>
<Send size={16} />
Send
</button>
</form>
</div>
{/* Claw Tool & Console Log Panel */}
<div className="glass" style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden", borderLeft: "1px solid var(--border-color)" }}>
<div style={{ padding: "16px 20px", borderBottom: "1px solid var(--border-color)", background: "rgba(255,255,255,0.01)" }}>
<h3 style={{ fontSize: "14px", display: "flex", alignItems: "center", gap: "8px" }}>
<Terminal size={16} style={{ color: "var(--accent-cyan)" }} />
Claw Tool Console
</h3>
</div>
<div style={{ flex: 1, padding: "16px", background: "#05070a", fontFamily: "var(--font-mono)", fontSize: "11px", color: "#a5f3fc", overflowY: "auto", display: "flex", flexDirection: "column", gap: "8px" }}>
{clawTerminalLogs.length === 0 ? (
<div style={{ color: "var(--text-muted)", fontStyle: "italic" }}>Console logs will stream here as Claw calls CLI and API tools...</div>
) : (
clawTerminalLogs.map((log, i) => (
<div key={i} style={{ whiteSpace: "pre-wrap", wordBreak: "break-all" }}>
<span style={{ color: "var(--text-muted)" }}>&gt;</span> {log}
</div>
))
)}
<div ref={terminalEndRef} />
</div>
</div>
</div>
)}
{/* TAB 3: OPSAGENT HUB */}
{activeTab === "ops" && (
<div className="fade-in" style={{ display: "grid", gridTemplateColumns: "1fr 400px", gap: "24px", height: "calc(100vh - 140px)" }}>
{/* Left Column: Diagnostics and Approvals */}
<div style={{ display: "flex", flexDirection: "column", gap: "20px", overflowY: "auto" }}>
{/* Pending Actions */}
<div className="glass" style={{ padding: "24px" }}>
<h2 style={{ fontSize: "16px", marginBottom: "16px", display: "flex", alignItems: "center", gap: "8px" }}>
<ShieldAlert size={20} style={{ color: "var(--accent-amber)" }} />
Awaiting System Approvals (Approval Gate)
</h2>
{pendingApprovals.length === 0 ? (
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", padding: "40px", gap: "12px", border: "1px dashed var(--border-color)", borderRadius: "8px" }}>
<CheckCircle size={32} style={{ color: "var(--accent-emerald)" }} />
<h4 style={{ color: "var(--text-primary)" }}>No approvals pending</h4>
<p style={{ fontSize: "12px", color: "var(--text-muted)" }}>All systems are running clean and within normal parameters.</p>
</div>
) : (
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
{pendingApprovals.map((req) => (
<div key={req.id} style={{ border: "1px solid var(--border-color)", borderRadius: "8px", background: "rgba(255,255,255,0.02)", overflow: "hidden" }}>
<div style={{ padding: "16px", borderBottom: "1px solid var(--border-color)", display: "flex", justifyContent: "space-between", alignItems: "center", background: "rgba(245,158,11,0.03)" }}>
<div>
<span style={{ fontSize: "11px", fontWeight: "700", textTransform: "uppercase", background: "rgba(245,158,11,0.15)", color: "var(--accent-amber)", padding: "2px 6px", borderRadius: "4px", marginRight: "8px" }}>
{req.action.replace("_", " ")}
</span>
<span style={{ fontSize: "13px", color: "var(--text-primary)", fontWeight: "600" }}>Target: {req.targetType.toUpperCase()} ({req.targetId})</span>
</div>
<span style={{ fontSize: "11px", color: "var(--text-muted)" }}>{req.timestamp}</span>
</div>
<div style={{ padding: "16px" }}>
<p style={{ fontSize: "13px", color: "var(--text-secondary)", lineHeight: "1.5", marginBottom: "16px" }}>{req.details}</p>
<div style={{ display: "flex", gap: "10px", justifyContent: "flex-end" }}>
<button
onClick={() => handleReject(req.id)}
style={{ padding: "8px 16px", border: "1px solid var(--accent-rose)", borderRadius: "6px", background: "transparent", color: "var(--accent-rose)", fontWeight: "600", cursor: "pointer", display: "flex", alignItems: "center", gap: "6px" }}
>
<XCircle size={14} />
Reject
</button>
<button
onClick={() => handleApprove(req.id, req.action, req.targetId)}
style={{ padding: "8px 16px", border: "none", borderRadius: "6px", background: "linear-gradient(135deg, var(--accent-emerald), #059669)", color: "#fff", fontWeight: "600", cursor: "pointer", display: "flex", alignItems: "center", gap: "6px" }}
>
<CheckCircle size={14} />
Approve & Execute
</button>
</div>
</div>
</div>
))}
</div>
)}
</div>
{/* Diagnostics Panel */}
<div className="glass" style={{ padding: "24px" }}>
<h3 style={{ fontSize: "15px", marginBottom: "12px" }}>OpsAgent Diagnostics Tools</h3>
<p style={{ fontSize: "13px", color: "var(--text-secondary)", marginBottom: "16px" }}>Manually run automated checks across your container nodes.</p>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px" }}>
<div style={{ padding: "12px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "rgba(255,255,255,0.01)" }}>
<span style={{ fontSize: "12px", fontWeight: "600" }}>K8s Diagnostic</span>
<button
onClick={() => {
setOpsLogs(prev => [...prev, `[Manual Trigger] Initiated Kubernetes diagnostics check for namespace 'default'...`]);
setTimeout(() => {
setOpsLogs(prev => [...prev, `[OpsAgent] web-pod-xyz logs scanned. DB connection failed.`]);
}, 1000);
}}
style={{ width: "100%", padding: "8px", border: "none", borderRadius: "4px", background: "rgba(6, 182, 212, 0.15)", color: "var(--accent-cyan)", fontWeight: "600", fontSize: "11px", cursor: "pointer", marginTop: "8px" }}
>
Scan Namespace
</button>
</div>
<div style={{ padding: "12px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "rgba(255,255,255,0.01)" }}>
<span style={{ fontSize: "12px", fontWeight: "600" }}>Proxmox Auditor</span>
<button
onClick={() => {
setOpsLogs(prev => [...prev, `[Manual Trigger] Querying Proxmox host 192.168.8.225 for LXC disk metrics...`]);
setTimeout(() => {
setOpsLogs(prev => [...prev, `[OpsAgent] VMID 102 checked: 94% storage load. VMID 105 checked: 52% load.`]);
}, 1000);
}}
style={{ width: "100%", padding: "8px", border: "none", borderRadius: "4px", background: "rgba(139, 92, 246, 0.15)", color: "var(--accent-violet)", fontWeight: "600", fontSize: "11px", cursor: "pointer", marginTop: "8px" }}
>
Audit Disk Usage
</button>
</div>
</div>
</div>
</div>
{/* Right Column: Execution Live Terminal */}
<div className="glass" style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }}>
<div style={{ padding: "16px 20px", borderBottom: "1px solid var(--border-color)", background: "rgba(255,255,255,0.01)" }}>
<h3 style={{ fontSize: "14px" }}>OpsAgent Execution Terminal Logs</h3>
</div>
<div style={{ flex: 1, padding: "16px", background: "#05070a", fontFamily: "var(--font-mono)", fontSize: "11px", color: "#a3e635", overflowY: "auto", display: "flex", flexDirection: "column", gap: "8px" }}>
{opsLogs.map((log, i) => (
<div key={i} style={{ lineBreak: "anywhere" }}>{log}</div>
))}
</div>
</div>
</div>
)}
{/* TAB 4: CLINICAL WORKSPACE */}
{activeTab === "curio" && (
<div className="fade-in" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "24px", height: "calc(100vh - 140px)" }}>
{/* Doctor Dictation Section */}
<div className="glass" style={{ padding: "24px", display: "flex", flexDirection: "column", gap: "16px", height: "100%", overflowY: "auto" }}>
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
<HeartPulse style={{ color: "var(--accent-emerald)" }} size={24} />
<div>
<h2 style={{ fontSize: "16px" }}>Clinical Scribe Workspace</h2>
<span style={{ fontSize: "11px", color: "var(--text-muted)" }}>Uses ClinicalIntakeWorkflow (Temporal Task Queue)</span>
</div>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: "6px" }}>
<label style={{ fontSize: "12px", color: "var(--text-secondary)", fontWeight: "600" }}>Raw Dictation Input</label>
<textarea
value={dictationText}
onChange={(e) => setDictationText(e.target.value)}
style={{ width: "100%", height: "200px", padding: "16px", border: "1px solid var(--border-color)", borderRadius: "8px", background: "var(--bg-secondary)", color: "var(--text-primary)", outline: "none", resize: "none", fontSize: "14px", lineHeight: "1.5" }}
/>
</div>
<button
onClick={handleProcessClinical}
disabled={isProcessingClinical || !dictationText}
style={{ width: "100%", padding: "12px", border: "none", borderRadius: "8px", background: "var(--accent-emerald)", color: "#000", fontWeight: "600", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: "8px" }}
>
{isProcessingClinical ? (
<>
<RefreshCw size={16} className="spin" style={{ animation: "spin 2s linear infinite" }} />
Structuring Dictation via LLM...
</>
) : (
<>
<Play size={16} />
Submit to ClinicalIntake Workflow
</>
)}
</button>
</div>
{/* Structuring Result Output */}
<div className="glass" style={{ padding: "24px", display: "flex", flexDirection: "column", gap: "16px", height: "100%", overflowY: "auto" }}>
<h3 style={{ fontSize: "15px", borderBottom: "1px solid var(--border-color)", paddingBottom: "12px" }}>Structured Output (SOAP Note)</h3>
{clinicalNote ? (
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
<div style={{ display: "grid", gridTemplateColumns: "1fr", gap: "12px" }}>
<div>
<span style={{ fontSize: "11px", fontWeight: "700", color: "var(--accent-emerald)" }}>SUBJECTIVE</span>
<p style={{ fontSize: "13px", color: "var(--text-secondary)", marginTop: "4px" }}>{clinicalNote.subjective}</p>
</div>
<div>
<span style={{ fontSize: "11px", fontWeight: "700", color: "var(--accent-emerald)" }}>OBJECTIVE</span>
<p style={{ fontSize: "13px", color: "var(--text-secondary)", marginTop: "4px" }}>{clinicalNote.objective}</p>
</div>
<div>
<span style={{ fontSize: "11px", fontWeight: "700", color: "var(--accent-emerald)" }}>ASSESSMENT</span>
<p style={{ fontSize: "13px", color: "var(--text-secondary)", marginTop: "4px" }}>{clinicalNote.assessment}</p>
</div>
<div>
<span style={{ fontSize: "11px", fontWeight: "700", color: "var(--accent-emerald)" }}>PLAN</span>
<p style={{ fontSize: "13px", color: "var(--text-secondary)", marginTop: "4px" }}>{clinicalNote.plan}</p>
</div>
</div>
<div style={{ borderTop: "1px solid var(--border-color)", paddingTop: "16px" }}>
<h4 style={{ fontSize: "12px", color: "var(--text-primary)", marginBottom: "8px" }}>Generated Billing Codes (ICD-10 / CPT)</h4>
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: "12px" }}>
<thead>
<tr style={{ textAlign: "left", color: "var(--text-muted)", borderBottom: "1px solid var(--border-color)" }}>
<th style={{ padding: "8px" }}>Code</th>
<th style={{ padding: "8px" }}>Description</th>
</tr>
</thead>
<tbody>
{billingCodes.map((bc, idx) => (
<tr key={idx} style={{ borderBottom: "1px solid rgba(255,255,255,0.02)" }}>
<td style={{ padding: "8px", fontWeight: "600", color: "var(--accent-cyan)" }}>{bc.code}</td>
<td style={{ padding: "8px", color: "var(--text-secondary)" }}>{bc.desc}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
) : (
<div style={{ display: "flex", flex: 1, alignItems: "center", justifyContent: "center", color: "var(--text-muted)", fontSize: "13px", fontStyle: "italic", border: "1px dashed var(--border-color)", borderRadius: "8px" }}>
No workflow submitted yet. Enter dictation and click submit.
</div>
)}
</div>
</div>
)}
{/* TAB 5: WORKFLOW MONITOR */}
{activeTab === "logs" && (
<div className="fade-in" style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
<div className="glass" style={{ padding: "24px" }}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "16px" }}>
<div>
<h3 style={{ fontSize: "16px" }}>Durable Execution Logs</h3>
<p style={{ fontSize: "12px", color: "var(--text-muted)" }}>Temporal workflows audit records inside the local postgres cluster.</p>
</div>
<button
onClick={() => {
setWorkflows(prev => [
...prev,
{ id: `wf-manual-${Math.floor(Math.random()*900+100)}`, name: "GumboSummarizeWorkflow", agent: "Gumbo", target: "wiki-summary.txt", status: "completed", result: "Completed" }
]);
}}
style={{ padding: "8px 14px", border: "none", borderRadius: "6px", background: "rgba(255,255,255,0.05)", color: "var(--text-primary)", fontWeight: "600", cursor: "pointer", fontSize: "12px" }}
>
Refresh List
</button>
</div>
<div style={{ overflowX: "auto" }}>
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: "13px" }}>
<thead>
<tr style={{ borderBottom: "1px solid var(--border-color)", color: "var(--text-muted)", textAlign: "left" }}>
<th style={{ padding: "12px 16px" }}>Workflow ID</th>
<th style={{ padding: "12px 16px" }}>Workflow Name</th>
<th style={{ padding: "12px 16px" }}>Assigned Agent</th>
<th style={{ padding: "12px 16px" }}>Target</th>
<th style={{ padding: "12px 16px" }}>Status</th>
<th style={{ padding: "12px 16px" }}>Result</th>
</tr>
</thead>
<tbody>
{workflows.map((wf) => (
<tr key={wf.id} style={{ borderBottom: "1px solid var(--border-color)", background: "rgba(255,255,255,0.005)" }}>
<td style={{ padding: "12px 16px", fontFamily: "var(--font-mono)", fontSize: "12px" }}>{wf.id}</td>
<td style={{ padding: "12px 16px", fontWeight: "600" }}>{wf.name}</td>
<td style={{ padding: "12px 16px" }}>{wf.agent}</td>
<td style={{ padding: "12px 16px", color: "var(--text-secondary)" }}>{wf.target}</td>
<td style={{ padding: "12px 16px" }}>
<div style={{ display: "flex", alignItems: "center", gap: "6px" }}>
<span style={{ width: "6px", height: "6px", borderRadius: "50%" }} className={wf.status === "running" ? "pulse-amber" : "pulse-emerald"}></span>
<span style={{ textTransform: "capitalize", fontWeight: "600", color: wf.status === "running" ? "var(--accent-amber)" : "var(--text-secondary)" }}>
{wf.status}
</span>
</div>
</td>
<td style={{ padding: "12px 16px", color: wf.status === "running" ? "var(--text-muted)" : "var(--text-primary)" }}>{wf.result}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
)}
</div>
</main>
</div>
);
}