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",
"answer": interaction.current_agent.last_answer,
"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 {},
"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())
}
query_resp_history.append(query_resp)

View File

@ -10,7 +10,7 @@ function App() {
const [currentView, setCurrentView] = useState('blocks');
const [responseData, setResponseData] = useState(null);
const [isOnline, setIsOnline] = useState(false);
const [isMounted, setIsMounted] = useState(true);
const [status, setStatus] = useState('No agent working.');
const messagesEndRef = useRef(null);
useEffect(() => {
@ -22,14 +22,6 @@ function App() {
return () => clearInterval(intervalId);
}, [messages]);
useEffect(() => {
const intervalId = setInterval(() => {
scrollToBottom();
}, 7000);
return () => clearInterval(intervalId);
}, [messages]);
const checkHealth = async () => {
try {
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 () => {
try {
const timestamp = new Date().getTime();
const res = await axios.get(`http://0.0.0.0:8000/screenshots/updated_screen.png?timestamp=${timestamp}`, {
responseType: 'blob'
});
if (isMounted) {
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()
};
});
}
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);
if (isMounted) {
setResponseData((prev) => ({
...prev,
screenshot: 'placeholder.png',
screenshotTimestamp: new Date().getTime()
}));
}
setResponseData((prev) => ({
...prev,
screenshot: 'placeholder.png',
screenshotTimestamp: new Date().getTime()
}));
}
};
const normalizeAnswer = (answer) => answer.trim().toLowerCase();
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
const fetchLatestAnswer = async () => {
try {
const res = await axios.get('http://0.0.0.0:8000/latest_answer');
const data = res.data;
const normalizedAnswer = normalizeAnswer(data.answer);
const answerExists = messages.some(
(msg) => normalizeAnswer(msg.content) === normalizedAnswer && data.answer != undefined
(msg) => msg.timestamp === data.timestamp && data.answer != undefined
);
if (!answerExists) {
setMessages((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) {
console.error("Error fetching latest answer:", error);
@ -179,7 +168,7 @@ function App() {
)}
<div ref={messagesEndRef} />
</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>}
<form onSubmit={handleSubmit} className="input-form">
<input

View File

@ -44,6 +44,7 @@ class Agent():
memory_compression=False)
self.tools = {}
self.blocks_result = []
self.success = True
self.last_answer = ""
self.status_message = "Haven't started yet"
self.verbose = verbose
@ -69,10 +70,18 @@ class Agent():
def get_blocks(self) -> list:
return self.blocks_result
@property
def get_status_message(self) -> str:
return self.status_message
@property
def get_tools(self) -> dict:
return self.tools
@property
def get_blocks_result(self) -> list:
return self.blocks_result
def add_tool(self, name: str, tool: Callable) -> None:
if tool is not Callable:
raise TypeError("Tool must be a callable object (a method)")
@ -145,9 +154,6 @@ class Agent():
loop = asyncio.get_event_loop()
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:
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.
"""
feedback = ""
success = False
success = True
blocks = None
if answer.startswith("```"):
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():
feedback = ""
blocks, save_path = tool.load_exec_block(answer)
@ -210,6 +217,7 @@ class Agent():
success = not tool.execution_failure_check(output)
self.blocks_result.append(executorResult(block, feedback, success, name))
if not success:
self.success = False
self.memory.push('user', feedback)
return False, feedback
self.memory.push('user', feedback)