fix : status display on frontend

This commit is contained in:
martin legrand 2025-04-18 17:18:11 +02:00
parent c030b55521
commit c9f6d76d30
3 changed files with 41 additions and 44 deletions

4
api.py
View File

@ -136,9 +136,9 @@ async def get_latest_answer():
"done": "false", "done": "false",
"answer": interaction.current_agent.last_answer, "answer": interaction.current_agent.last_answer,
"agent_name": interaction.current_agent.agent_name if interaction.current_agent else "None", "agent_name": interaction.current_agent.agent_name if interaction.current_agent else "None",
"success": "false", "success": interaction.current_agent.success,
"blocks": {f'{i}': block.jsonify() for i, block in enumerate(interaction.current_agent.get_blocks_result())} if interaction.current_agent else {}, "blocks": {f'{i}': block.jsonify() for i, block in enumerate(interaction.current_agent.get_blocks_result())} if interaction.current_agent else {},
"status": interaction.current_agent.status_message if interaction.current_agent else "No status available", "status": interaction.current_agent.get_status_message if interaction.current_agent else "No status available",
"timestamp": str(time.time()) "timestamp": str(time.time())
} }
query_resp_history.append(query_resp) query_resp_history.append(query_resp)

View File

@ -10,7 +10,7 @@ function App() {
const [currentView, setCurrentView] = useState('blocks'); const [currentView, setCurrentView] = useState('blocks');
const [responseData, setResponseData] = useState(null); const [responseData, setResponseData] = useState(null);
const [isOnline, setIsOnline] = useState(false); const [isOnline, setIsOnline] = useState(false);
const [isMounted, setIsMounted] = useState(true); const [status, setStatus] = useState('No agent working.');
const messagesEndRef = useRef(null); const messagesEndRef = useRef(null);
useEffect(() => { useEffect(() => {
@ -22,14 +22,6 @@ function App() {
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
}, [messages]); }, [messages]);
useEffect(() => {
const intervalId = setInterval(() => {
scrollToBottom();
}, 7000);
return () => clearInterval(intervalId);
}, [messages]);
const checkHealth = async () => { const checkHealth = async () => {
try { try {
await axios.get('http://0.0.0.0:8000/health'); await axios.get('http://0.0.0.0:8000/health');
@ -41,57 +33,54 @@ function App() {
} }
}; };
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
const fetchScreenshot = async () => { const fetchScreenshot = async () => {
try { try {
const timestamp = new Date().getTime(); const timestamp = new Date().getTime();
const res = await axios.get(`http://0.0.0.0:8000/screenshots/updated_screen.png?timestamp=${timestamp}`, { const res = await axios.get(`http://0.0.0.0:8000/screenshots/updated_screen.png?timestamp=${timestamp}`, {
responseType: 'blob' responseType: 'blob'
}); });
if (isMounted) { console.log('Screenshot fetched successfully');
console.log('Screenshot fetched successfully'); const imageUrl = URL.createObjectURL(res.data);
const imageUrl = URL.createObjectURL(res.data); setResponseData((prev) => {
setResponseData((prev) => { if (prev?.screenshot && prev.screenshot !== 'placeholder.png') {
if (prev?.screenshot && prev.screenshot !== 'placeholder.png') { URL.revokeObjectURL(prev.screenshot);
URL.revokeObjectURL(prev.screenshot); }
} return {
return { ...prev,
...prev, screenshot: imageUrl,
screenshot: imageUrl, screenshotTimestamp: new Date().getTime()
screenshotTimestamp: new Date().getTime() };
}; });
});
}
} catch (err) { } catch (err) {
console.error('Error fetching screenshot:', err); console.error('Error fetching screenshot:', err);
if (isMounted) { setResponseData((prev) => ({
setResponseData((prev) => ({ ...prev,
...prev, screenshot: 'placeholder.png',
screenshot: 'placeholder.png', screenshotTimestamp: new Date().getTime()
screenshotTimestamp: new Date().getTime() }));
}));
}
} }
}; };
const normalizeAnswer = (answer) => answer.trim().toLowerCase(); const normalizeAnswer = (answer) => answer.trim().toLowerCase();
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
const fetchLatestAnswer = async () => { const fetchLatestAnswer = async () => {
try { try {
const res = await axios.get('http://0.0.0.0:8000/latest_answer'); const res = await axios.get('http://0.0.0.0:8000/latest_answer');
const data = res.data; const data = res.data;
const normalizedAnswer = normalizeAnswer(data.answer);
const answerExists = messages.some( const answerExists = messages.some(
(msg) => normalizeAnswer(msg.content) === normalizedAnswer && data.answer != undefined (msg) => msg.timestamp === data.timestamp && data.answer != undefined
); );
if (!answerExists) { if (!answerExists) {
setMessages((prev) => [ setMessages((prev) => [
...prev, ...prev,
{ type: 'agent', content: data.answer, agentName: data.agent_name }, { type: 'agent', content: data.answer, agentName: data.agent_name, status: data.status, timestamp: data.timestamp },
]); ]);
setStatus(data.status);
scrollToBottom();
} }
} catch (error) { } catch (error) {
console.error("Error fetching latest answer:", error); console.error("Error fetching latest answer:", error);
@ -179,7 +168,7 @@ function App() {
)} )}
<div ref={messagesEndRef} /> <div ref={messagesEndRef} />
</div> </div>
{isOnline && isLoading && <div className="loading-animation">Thinking...</div>} {isOnline && <div className="loading-animation">{status}</div>}
{!isLoading && !isOnline && <p className="loading-animation">System offline. Deploy backend first.</p>} {!isLoading && !isOnline && <p className="loading-animation">System offline. Deploy backend first.</p>}
<form onSubmit={handleSubmit} className="input-form"> <form onSubmit={handleSubmit} className="input-form">
<input <input

View File

@ -44,6 +44,7 @@ class Agent():
memory_compression=False) memory_compression=False)
self.tools = {} self.tools = {}
self.blocks_result = [] self.blocks_result = []
self.success = True
self.last_answer = "" self.last_answer = ""
self.status_message = "Haven't started yet" self.status_message = "Haven't started yet"
self.verbose = verbose self.verbose = verbose
@ -68,10 +69,18 @@ class Agent():
@property @property
def get_blocks(self) -> list: def get_blocks(self) -> list:
return self.blocks_result return self.blocks_result
@property
def get_status_message(self) -> str:
return self.status_message
@property @property
def get_tools(self) -> dict: def get_tools(self) -> dict:
return self.tools return self.tools
@property
def get_blocks_result(self) -> list:
return self.blocks_result
def add_tool(self, name: str, tool: Callable) -> None: def add_tool(self, name: str, tool: Callable) -> None:
if tool is not Callable: if tool is not Callable:
@ -145,9 +154,6 @@ class Agent():
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
return await loop.run_in_executor(self.executor, lambda: speech_module.speak(messages[random.randint(0, len(messages)-1)])) return await loop.run_in_executor(self.executor, lambda: speech_module.speak(messages[random.randint(0, len(messages)-1)]))
def get_blocks_result(self) -> list:
return self.blocks_result
def get_last_tool_type(self) -> str: def get_last_tool_type(self) -> str:
return self.blocks_result[-1].tool_type if len(self.blocks_result) > 0 else None return self.blocks_result[-1].tool_type if len(self.blocks_result) > 0 else None
@ -194,11 +200,12 @@ class Agent():
Execute all the tools the agent has and return the result. Execute all the tools the agent has and return the result.
""" """
feedback = "" feedback = ""
success = False success = True
blocks = None blocks = None
if answer.startswith("```"): if answer.startswith("```"):
answer = "I will execute:\n" + answer # there should always be a text before blocks for the function that display answer answer = "I will execute:\n" + answer # there should always be a text before blocks for the function that display answer
self.success = True
for name, tool in self.tools.items(): for name, tool in self.tools.items():
feedback = "" feedback = ""
blocks, save_path = tool.load_exec_block(answer) blocks, save_path = tool.load_exec_block(answer)
@ -210,6 +217,7 @@ class Agent():
success = not tool.execution_failure_check(output) success = not tool.execution_failure_check(output)
self.blocks_result.append(executorResult(block, feedback, success, name)) self.blocks_result.append(executorResult(block, feedback, success, name))
if not success: if not success:
self.success = False
self.memory.push('user', feedback) self.memory.push('user', feedback)
return False, feedback return False, feedback
self.memory.push('user', feedback) self.memory.push('user', feedback)