import React, { useState, useEffect, useRef, useCallback } from "react"; import ReactMarkdown from "react-markdown"; import axios from "axios"; import "./App.css"; import { ThemeToggle } from "./components/ThemeToggle"; import { ResizableLayout } from "./components/ResizableLayout"; import faviconPng from "./logo.png"; const BACKEND_URL = process.env.REACT_APP_BACKEND_URL; console.log("Using backend URL:", BACKEND_URL); function App() { const [query, setQuery] = useState(""); const [messages, setMessages] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [currentView, setCurrentView] = useState("blocks"); const [responseData, setResponseData] = useState(null); const [isOnline, setIsOnline] = useState(false); const [status, setStatus] = useState("Agents ready"); const [expandedReasoning, setExpandedReasoning] = useState(new Set()); const messagesEndRef = useRef(null); const fetchLatestAnswer = useCallback(async () => { try { const res = await axios.get(`${BACKEND_URL}/latest_answer`); const data = res.data; updateData(data); if (!data.answer || data.answer.trim() === "") { return; } const normalizedNewAnswer = normalizeAnswer(data.answer); const answerExists = messages.some( (msg) => normalizeAnswer(msg.content) === normalizedNewAnswer ); if (!answerExists) { setMessages((prev) => [ ...prev, { type: "agent", content: data.answer, reasoning: data.reasoning, agentName: data.agent_name, status: data.status, uid: data.uid, }, ]); setStatus(data.status); scrollToBottom(); } else { console.log("Duplicate answer detected, skipping:", data.answer); } } catch (error) { console.error("Error fetching latest answer:", error); } }, [messages]); useEffect(() => { const intervalId = setInterval(() => { checkHealth(); fetchLatestAnswer(); fetchScreenshot(); }, 3000); return () => clearInterval(intervalId); }, [fetchLatestAnswer]); const checkHealth = async () => { try { await axios.get(`${BACKEND_URL}/health`); setIsOnline(true); console.log("System is online"); } catch { setIsOnline(false); console.log("System is offline"); } }; const fetchScreenshot = async () => { try { const timestamp = new Date().getTime(); const res = await axios.get( `${BACKEND_URL}/screenshots/updated_screen.png?timestamp=${timestamp}`, { responseType: "blob", } ); console.log("Screenshot fetched successfully"); const imageUrl = URL.createObjectURL(res.data); setResponseData((prev) => { if (prev?.screenshot && prev.screenshot !== "placeholder.png") { URL.revokeObjectURL(prev.screenshot); } return { ...prev, screenshot: imageUrl, screenshotTimestamp: new Date().getTime(), }; }); } catch (err) { console.error("Error fetching screenshot:", err); setResponseData((prev) => ({ ...prev, screenshot: "placeholder.png", screenshotTimestamp: new Date().getTime(), })); } }; const normalizeAnswer = (answer) => { return answer .trim() .toLowerCase() .replace(/\s+/g, " ") .replace(/[.,!?]/g, ""); }; const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }; const toggleReasoning = (messageIndex) => { setExpandedReasoning((prev) => { const newSet = new Set(prev); if (newSet.has(messageIndex)) { newSet.delete(messageIndex); } else { newSet.add(messageIndex); } return newSet; }); }; const updateData = (data) => { setResponseData((prev) => ({ ...prev, blocks: data.blocks || prev.blocks || null, done: data.done, answer: data.answer, agent_name: data.agent_name, status: data.status, uid: data.uid, })); }; const handleStop = async (e) => { e.preventDefault(); checkHealth(); setIsLoading(false); setError(null); try { await axios.get(`${BACKEND_URL}/stop`); setStatus("Requesting stop..."); } catch (err) { console.error("Error stopping the agent:", err); } }; const handleSubmit = async (e) => { e.preventDefault(); checkHealth(); if (!query.trim()) { console.log("Empty query"); return; } setMessages((prev) => [...prev, { type: "user", content: query }]); setIsLoading(true); setError(null); try { console.log("Sending query:", query); setQuery("waiting for response..."); const res = await axios.post(`${BACKEND_URL}/query`, { query, tts_enabled: false, }); setQuery("Enter your query..."); console.log("Response:", res.data); const data = res.data; updateData(data); } catch (err) { console.error("Error:", err); setError("Failed to process query."); setMessages((prev) => [ ...prev, { type: "error", content: "Error: Unable to get a response." }, ]); } finally { console.log("Query completed"); setIsLoading(false); setQuery(""); } }; const handleGetScreenshot = async () => { try { setCurrentView("screenshot"); } catch (err) { setError("Browser not in use"); } }; return (
AgenticSeek

AgenticSeek

{isOnline ? "Online" : "Offline"}
GitHub

Chat Interface

{messages.length === 0 ? (

No messages yet. Type below to start!

) : ( messages.map((msg, index) => (
{msg.type === "agent" && ( {msg.agentName} )} {msg.type === "agent" && msg.reasoning && expandedReasoning.has(index) && (
{msg.reasoning}
)} {msg.type === "agent" && ( )}
{msg.content}
)) )}
{isOnline &&
{status}
} {!isLoading && !isOnline && (

System offline. Deploy backend first.

)}
setQuery(e.target.value)} placeholder="Type your query..." disabled={isLoading} />

Computer View

{error &&

{error}

} {currentView === "blocks" ? (
{responseData && responseData.blocks && Object.values(responseData.blocks).length > 0 ? ( Object.values(responseData.blocks).map((block, index) => (

Tool: {block.tool_type}

{block.block}

Feedback: {block.feedback}

{block.success ? (

Success

) : (

Failure

)}
)) ) : (

Tool: No tool in use

No file opened
)}
) : (
Screenshot { e.target.src = "placeholder.png"; console.error("Failed to load screenshot"); }} key={responseData?.screenshotTimestamp || "default"} />
)}
); } export default App;