Files
browser-use/examples/fastapi/static/index.html

224 lines
7.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Browser Agent Controller</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.control-panel {
display: grid;
gap: 10px;
margin-top: 20px;
}
button {
padding: 10px;
border: none;
border-radius: 4px;
background-color: #007bff;
color: white;
cursor: pointer;
transition: background-color 0.3s;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
button:hover:not(:disabled) {
background-color: #0056b3;
}
#status {
margin-top: 20px;
padding: 10px;
border-radius: 4px;
}
.status-running { background-color: #d4edda; color: #155724; }
.status-paused { background-color: #fff3cd; color: #856404; }
.status-stopped { background-color: #f8d7da; color: #721c24; }
.status-not-created { background-color: #e2e3e5; color: #383d41; }
.status-ready { background-color: #cce5ff; color: #004085; }
textarea {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ddd;
border-radius: 4px;
resize: vertical;
}
#logContainer {
margin-top: 20px;
padding: 10px;
background-color: #f8f9fa;
border-radius: 4px;
border: 1px solid #ddd;
height: 300px;
overflow-y: auto;
font-family: monospace;
font-size: 14px;
white-space: pre-wrap;
}
.log-entry {
margin: 2px 0;
padding: 2px 5px;
}
.button-group {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>Browser Agent Controller</h1>
<div class="control-panel">
<textarea id="taskInput" rows="3" placeholder="Enter your task here..."></textarea>
<div class="button-group">
<button id="runBtn" onclick="runAgent()">Run Agent</button>
<button id="pauseBtn" onclick="pauseAgent()" disabled>Pause</button>
<button id="resumeBtn" onclick="resumeAgent()" disabled>Resume</button>
<button id="stopBtn" onclick="stopAgent()" disabled>Stop</button>
</div>
</div>
<div id="status" class="status-not-created">
Status: Not Created
</div>
<div id="logContainer">
<div id="logs"></div>
</div>
</div>
<script>
let statusCheckInterval;
let eventSource;
function setupLogging() {
if (eventSource) {
eventSource.close();
}
eventSource = new EventSource('/logs');
const logsDiv = document.getElementById('logs');
eventSource.addEventListener('log', function(event) {
const logEntry = document.createElement('div');
logEntry.className = 'log-entry';
logEntry.textContent = event.data;
logsDiv.appendChild(logEntry);
logsDiv.scrollTop = logsDiv.scrollHeight;
});
eventSource.onerror = function(error) {
console.error('EventSource failed:', error);
eventSource.close();
setTimeout(setupLogging, 5000); // Try to reconnect after 5 seconds
};
}
async function runAgent() {
const task = document.getElementById('taskInput').value;
if (!task) {
alert('Please enter a task');
return;
}
try {
const response = await fetch('/agent/run', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ task }),
});
if (response.ok) {
startStatusCheck();
document.getElementById('taskInput').disabled = true;
}
} catch (error) {
console.error('Error:', error);
alert('Failed to run agent');
}
}
async function pauseAgent() {
try {
await fetch('/agent/pause', { method: 'POST' });
} catch (error) {
console.error('Error:', error);
alert('Failed to pause agent');
}
}
async function resumeAgent() {
try {
await fetch('/agent/resume', { method: 'POST' });
} catch (error) {
console.error('Error:', error);
alert('Failed to resume agent');
}
}
async function stopAgent() {
try {
await fetch('/agent/stop', { method: 'POST' });
document.getElementById('taskInput').disabled = false;
} catch (error) {
console.error('Error:', error);
alert('Failed to stop agent');
}
}
async function checkStatus() {
try {
const response = await fetch('/agent/status');
const data = await response.json();
const statusDiv = document.getElementById('status');
statusDiv.className = `status-${data.status}`;
statusDiv.textContent = `Status: ${data.status.charAt(0).toUpperCase() + data.status.slice(1)}`;
// Update buttons based on status
document.getElementById('runBtn').disabled = data.status === 'running';
document.getElementById('pauseBtn').disabled = data.status !== 'running';
document.getElementById('resumeBtn').disabled = data.status !== 'paused';
document.getElementById('stopBtn').disabled = data.status === 'stopped' || data.status === 'not_created';
if (data.task) {
statusDiv.textContent += `\nTask: ${data.task}`;
}
} catch (error) {
console.error('Error checking status:', error);
}
}
function startStatusCheck() {
// Check status immediately
checkStatus();
// Then check every 2 seconds
if (!statusCheckInterval) {
statusCheckInterval = setInterval(checkStatus, 2000);
}
}
// Initial setup
setupLogging();
checkStatus();
</script>
</body>
</html>