// =========================== // State Management // =========================== let taskStats = { total: 0, successful: 0, times: [], }; // Load stats from localStorage function loadStats() { const savedStats = localStorage.getItem("taskStats"); if (savedStats) { taskStats = JSON.parse(savedStats); updateStatsDisplay(); } } // Save stats to localStorage function saveStats() { localStorage.setItem("taskStats", JSON.stringify(taskStats)); } // Update stats display function updateStatsDisplay() { document.getElementById("total-tasks").textContent = taskStats.total; document.getElementById("successful-tasks").textContent = taskStats.successful; if (taskStats.times.length > 0) { const avgTime = taskStats.times.reduce((a, b) => a + b, 0) / taskStats.times.length; document.getElementById("avg-time").textContent = avgTime.toFixed(1) + "s"; } } // =========================== // Main Functions // =========================== // Fill prompt textarea with example function fillPrompt(text) { document.getElementById("prompt").value = text.trim(); document.getElementById("prompt").focus(); } // Execute browser automation task async function executeTask() { const prompt = document.getElementById("prompt").value.trim(); if (!prompt) { showNotification("Please enter a task prompt", "error"); return; } // Show loading, hide results showLoading(true); hideResults(); disableButtons(true); const startTime = Date.now(); try { const response = await fetch("/execute", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ prompt }), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); const duration = ((Date.now() - startTime) / 1000).toFixed(1); // Update stats taskStats.total++; if (data.success) { taskStats.successful++; } taskStats.times.push(parseFloat(duration)); saveStats(); updateStatsDisplay(); // Hide loading showLoading(false); disableButtons(false); // Display results displayResults(data, duration); // Show notification if (data.success) { showNotification("Task completed successfully!", "success"); } else { showNotification( "Task failed. Check the output for details.", "error" ); } } catch (error) { console.error("Error:", error); showLoading(false); disableButtons(false); displayError(error.message); showNotification("Failed to execute task", "error"); } } // Display results function displayResults(data, duration) { const resultsSection = document.getElementById("results"); resultsSection.classList.add("active"); // Result title and output const resultIcon = document.getElementById("result-icon"); const resultTitleText = document.getElementById("result-title-text"); const resultOutput = document.getElementById("result-output"); if (data.success) { resultIcon.textContent = "✅"; resultIcon.className = "result-icon success-icon"; resultTitleText.textContent = "Success"; resultOutput.textContent = data.output || "Task completed successfully!"; } else { resultIcon.textContent = "❌"; resultIcon.className = "result-icon error-icon"; resultTitleText.textContent = "Error"; resultOutput.textContent = data.error || "An unknown error occurred"; } // Action history const actionHistoryBox = document.getElementById("action-history-box"); const actionHistory = document.getElementById("action-history"); if (data.action_history && data.action_history.length > 0) { actionHistoryBox.style.display = "block"; const historyHtml = data.action_history .map((action, index) => { const actionDetails = Object.entries(action) .filter(([key]) => key !== "action") .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) .join(", "); return `
${ index + 1 }. ${action.action.toUpperCase()} ${actionDetails ? "
" + actionDetails : ""}
`; }) .join(""); actionHistory.innerHTML = historyHtml; } else { actionHistoryBox.style.display = "none"; } // Screenshot const screenshotBox = document.getElementById("screenshot-box"); const screenshot = document.getElementById("screenshot"); if (data.screenshot) { screenshotBox.style.display = "block"; screenshot.src = "data:image/png;base64," + data.screenshot; } else { screenshotBox.style.display = "none"; } // Scroll to results setTimeout(() => { resultsSection.scrollIntoView({ behavior: "smooth", block: "start" }); }, 100); } // Display error function displayError(errorMessage) { const resultsSection = document.getElementById("results"); resultsSection.classList.add("active"); const resultIcon = document.getElementById("result-icon"); const resultTitleText = document.getElementById("result-title-text"); const resultOutput = document.getElementById("result-output"); resultIcon.textContent = "❌"; resultIcon.className = "result-icon error-icon"; resultTitleText.textContent = "Error"; resultOutput.textContent = `Failed to communicate with server:\n${errorMessage}`; // Hide action history and screenshot document.getElementById("action-history-box").style.display = "none"; document.getElementById("screenshot-box").style.display = "none"; } // Clear results function clearResults() { document.getElementById("prompt").value = ""; document.getElementById("results").classList.remove("active"); document.getElementById("action-history-box").style.display = "none"; document.getElementById("screenshot-box").style.display = "none"; showNotification("Results cleared", "info"); } // =========================== // UI Helper Functions // =========================== // Show/hide loading indicator function showLoading(show) { const loading = document.getElementById("loading"); if (show) { loading.classList.add("active"); } else { loading.classList.remove("active"); } } // Hide results section function hideResults() { document.getElementById("results").classList.remove("active"); } // Disable/enable buttons function disableButtons(disabled) { document.querySelectorAll(".btn").forEach((btn) => { btn.disabled = disabled; }); } // Show notification (simple toast) function showNotification(message, type = "info") { // Check if notification container exists, create if not let container = document.getElementById("notification-container"); if (!container) { container = document.createElement("div"); container.id = "notification-container"; container.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 10000; `; document.body.appendChild(container); } // Create notification element const notification = document.createElement("div"); notification.className = `notification notification-${type}`; const icon = { success: "✅", error: "❌", info: "ℹ️", warning: "⚠️", }[type] || "ℹ️"; const bgColor = { success: "#4caf50", error: "#f44336", info: "#2196f3", warning: "#ff9800", }[type] || "#2196f3"; notification.style.cssText = ` background: ${bgColor}; color: white; padding: 1rem 1.5rem; border-radius: 8px; margin-bottom: 10px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); display: flex; align-items: center; gap: 10px; min-width: 300px; animation: slideIn 0.3s ease; `; notification.innerHTML = ` ${icon} ${message} `; container.appendChild(notification); // Auto remove after 3 seconds setTimeout(() => { notification.style.animation = "slideOut 0.3s ease"; setTimeout(() => { notification.remove(); }, 300); }, 3000); } // =========================== // Event Listeners // =========================== // Initialize on page load document.addEventListener("DOMContentLoaded", function () { loadStats(); // Enter key to submit (Shift+Enter for new line) document.getElementById("prompt").addEventListener("keydown", function (e) { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); executeTask(); } }); // Add CSS for animations if (!document.getElementById("notification-animations")) { const style = document.createElement("style"); style.id = "notification-animations"; style.textContent = ` @keyframes slideIn { from { transform: translateX(400px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slideOut { from { transform: translateX(0); opacity: 1; } to { transform: translateX(400px); opacity: 0; } } `; document.head.appendChild(style); } }); // =========================== // Utility Functions // =========================== // Format date/time function formatDateTime(date) { return new Date(date).toLocaleString(); } // Copy text to clipboard async function copyToClipboard(text) { try { await navigator.clipboard.writeText(text); showNotification("Copied to clipboard!", "success"); } catch (err) { showNotification("Failed to copy", "error"); } } // Download screenshot function downloadScreenshot() { const screenshot = document.getElementById("screenshot"); if (screenshot.src) { const link = document.createElement("a"); link.href = screenshot.src; link.download = `manus-ai-screenshot-${Date.now()}.png`; link.click(); showNotification("Screenshot downloaded", "success"); } } // Export results as JSON function exportResults() { const resultOutput = document.getElementById("result-output").textContent; const actionHistory = document.getElementById("action-history").innerHTML; const data = { timestamp: new Date().toISOString(), output: resultOutput, actionHistory: actionHistory, stats: taskStats, }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json", }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = `manus-ai-results-${Date.now()}.json`; link.click(); URL.revokeObjectURL(url); showNotification("Results exported", "success"); } // Reset stats function resetStats() { if (confirm("Are you sure you want to reset all statistics?")) { taskStats = { total: 0, successful: 0, times: [], }; saveStats(); updateStatsDisplay(); showNotification("Statistics reset", "info"); } }