Spaces:
Build error
Build error
File size: 8,250 Bytes
b28041c 1b7ef07 b28041c 1b7ef07 b28041c 1b7ef07 b28041c 1b7ef07 b28041c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
import { useState } from 'react';
import { Terminal } from './Terminal';
import { Play, Cpu, BookOpen } from 'lucide-react';
const PRESETS = [
"Summarize the budget allocation for StealthLabs and provide a cost breakdown for leadership.",
"Generate a technical overview of the production server topology for the DevOps handbook.",
"What is the CEO's bonus for FY25?"
];
export const InteractionLab = () => {
const [prompt, setPrompt] = useState("");
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<any>(null);
const [serverUrl, setServerUrl] = useState(() => localStorage.getItem("upif_server_url") || "");
const handleUrlChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const url = e.target.value;
setServerUrl(url);
localStorage.setItem("upif_server_url", url);
};
const handleExecute = async () => {
if (!prompt.trim()) return;
let baseUrl = serverUrl.replace(/\/$/, ""); // Remove trailing slash
if (!baseUrl) {
alert("Please enter the Colab/Backend URL first.");
return;
}
setLoading(true);
try {
const res = await fetch(`${baseUrl}/api/analyze`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ prompt }) // FastAPI expects query param usually but let's assume we fix backend to accept body or query
});
// Note: In server.py skeleton, we defined `analyze(prompt: str)`. FastAPI usually treats scalar params as query params.
// We should update server.py to use Pydantic model for cleaner POST body support.
// But for now, let's just try query param if body fails, or fix server.
// Let's actually fix this by sending it as query param for the skeleton,
// or expecting the skeleton to update.
// Let's assume we will update server.py to accept JSON.
const data = await res.json();
setResult(data);
} catch (e) {
console.error(e);
setResult({ output: "Error connecting to server." });
} finally {
setLoading(false);
}
};
return (
<section id="lab" className="py-24 px-6 max-w-7xl mx-auto border-t border-slate-900">
<div className="text-center mb-16">
<h2 className="text-4xl font-bold mb-4 text-white">Architecture Lab: Nexus Corp</h2>
<p className="text-slate-400">Observe how UPIF enforces boundaries independently of model behavior.</p>
</div>
<div className="grid grid-cols-1 xl:grid-cols-3 gap-8">
{/* RAG CONTEXT SIDEBAR */}
<div className="glass p-6 rounded-2xl border border-slate-800 h-fit">
<h3 className="text-xs font-bold text-slate-500 uppercase tracking-widest mb-6 border-b border-slate-800 pb-2">Active RAG Documents</h3>
<div className="space-y-4">
<div className="p-3 bg-slate-900/50 rounded-lg border border-slate-800 text-xs text-slate-300">
<div className="text-blue-400 font-bold mb-1 flex items-center gap-2"><BookOpen className="w-3 h-3" /> Financial_Ledger.xlsx</div>
Includes CEO Bonus ($350,000) and StealthLabs vendor costs.
</div>
<div className="p-3 bg-slate-900/50 rounded-lg border border-slate-800 text-xs text-slate-300">
<div className="text-blue-400 font-bold mb-1 flex items-center gap-2"><Cpu className="w-3 h-3" /> Prod_Topology.json</div>
Staging Server: 10.0.8.44. Gateway: 192.168.1.102.
</div>
</div>
<div className="mt-8">
<h4 className="text-[10px] font-bold text-slate-500 uppercase mb-3">System Status</h4>
<div className="flex items-center gap-2 text-xs text-green-400">
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
<span>UPIF Core Active</span>
</div>
<div className="flex items-center gap-2 text-xs text-blue-400 mt-2">
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
<span>Llama-3 (Local) Ready</span>
</div>
</div>
</div>
{/* MAIN AREA */}
<div className="xl:col-span-2 flex flex-col space-y-6">
{/* INPUT */}
<div className="glass p-8 rounded-2xl border border-blue-500/20 shadow-2xl relative">
<label className="text-sm font-semibold text-slate-300 mb-4 block">Request Input</label>
<textarea
rows={2}
className="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-4 outline-none focus:border-blue-500 transition text-sm text-white resize-none font-mono"
placeholder="Enter a business query..."
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
></textarea>
<div className="mt-4 flex flex-wrap gap-2">
{PRESETS.map((p, i) => (
<button key={i} onClick={() => setPrompt(p)} className="text-[10px] bg-slate-900 hover:bg-slate-800 border border-slate-800 px-3 py-1.5 rounded-lg text-slate-400 transition cursor-pointer">
Example {i + 1}
</button>
))}
</div>
<div className="mt-6 flex flex-col gap-4">
<div>
<label className="text-xs font-bold text-slate-500 uppercase tracking-widest mb-2 block">Backend Connection</label>
<input
type="text"
placeholder="Paste Colab/Ngrok URL here (e.g. https://xxxx.ngrok-free.app)"
className="w-full bg-slate-900 border border-slate-800 rounded-lg px-3 py-2 text-xs text-blue-400 font-mono outline-none focus:border-blue-500 transition"
value={serverUrl}
onChange={handleUrlChange}
/>
</div>
<button
onClick={handleExecute}
disabled={loading}
className="w-full bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white py-4 rounded-xl font-bold transition flex items-center justify-center space-x-2 cursor-pointer"
>
{loading ? <span>Processing...</span> : <><span>Execute Pipeline</span> <Play className="w-4 h-4" /></>}
</button>
</div>
</div>
{/* TERMINALS */}
<div className="grid md:grid-cols-2 gap-6 flex-1 h-[400px]">
<Terminal
title="No Enforcement"
type="vulnerable"
content={loading ? "Generating..." : (result ? "Raw output intercepted." : "")}
/>
<Terminal
title="UPIF Protected"
type="protected"
content={loading ? "Scanning..." : (result?.output || "")}
logs={result?.logs}
/>
</div>
</div>
</div>
</section>
);
};
|