Spaces:
Build error
Build error
| import React, { useEffect, useState } from 'react'; | |
| export default function App() { | |
| const [browserFrame, setBrowserFrame] = useState<string>(""); | |
| const [logs, setLogs] = useState<string[]>([]); | |
| const [input, setInput] = useState(""); | |
| useEffect(() => { | |
| const eventSource = new EventSource("/api/stream"); | |
| eventSource.onmessage = (event) => { | |
| try { | |
| const data = JSON.parse(event.data); | |
| if (data.type === "frame") setBrowserFrame(data.data); | |
| if (data.type === "log") setLogs(prev => [...prev, data.data].slice(-10)); | |
| } catch (e) { | |
| console.error("SSE Parse Error", e); | |
| } | |
| }; | |
| return () => eventSource.close(); | |
| }, []); | |
| const sendMessage = async () => { | |
| if (!input) return; | |
| setLogs(prev => [...prev, `You: ${input}`]); | |
| await fetch("/api/chat", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ message: input }) | |
| }); | |
| setInput(""); | |
| }; | |
| return ( | |
| <div className="flex h-screen bg-zinc-950 text-zinc-200 font-sans"> | |
| <div className="w-80 flex flex-col border-r border-zinc-800 p-4 bg-zinc-900/50"> | |
| <h1 className="text-lg font-bold mb-4 text-blue-500 flex items-center gap-2"> | |
| <div className="w-3 h-3 bg-blue-500 rounded-full animate-pulse"></div> | |
| Polymorphic Agent | |
| </h1> | |
| <div className="flex-1 overflow-y-auto space-y-2 mb-4 scrollbar-hide"> | |
| {logs.map((log, i) => ( | |
| <div key={i} className="p-2 bg-zinc-800/50 rounded border border-zinc-700/50 text-xs"> | |
| {log} | |
| </div> | |
| ))} | |
| </div> | |
| <div className="flex gap-2"> | |
| <input | |
| className="flex-1 bg-zinc-800 border border-zinc-700 p-2 rounded text-sm focus:outline-none focus:border-blue-500" | |
| value={input} | |
| onChange={(e) => setInput(e.target.value)} | |
| onKeyDown={(e) => e.key === 'Enter' && sendMessage()} | |
| placeholder="Ask agent..." | |
| /> | |
| <button onClick={sendMessage} className="bg-blue-600 hover:bg-blue-500 px-3 py-1 rounded text-sm transition-colors"> | |
| Send | |
| </button> | |
| </div> | |
| </div> | |
| <div className="flex-1 bg-black flex flex-col relative"> | |
| <div className="absolute top-2 left-2 z-10 bg-black/60 px-2 py-1 rounded text-[10px] uppercase tracking-widest text-zinc-500 border border-zinc-800"> | |
| Live Nix Environment View | |
| </div> | |
| <div className="flex-1 flex items-center justify-center"> | |
| {browserFrame ? ( | |
| <img src={`data:image/jpeg;base64,${browserFrame}`} className="max-w-full max-h-full object-contain shadow-2xl" /> | |
| ) : ( | |
| <div className="flex flex-col items-center gap-3"> | |
| <div className="w-8 h-8 border-4 border-blue-500/20 border-t-blue-500 rounded-full animate-spin"></div> | |
| <div className="text-zinc-600 text-sm font-medium">Initializing Browser...</div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } |