Some checks failed
Beta Release / beta (push) Failing after 48s
Adds a WXT-based browser extension that replaces manual JS snippet injection for AI-driven browser testing. The extension auto-connects to the Muyue server via WebSocket on every page, using the exact same protocol as the existing snippet — zero backend changes needed. - Chrome/Edge (MV3) + Firefox (MV2) from single codebase via WXT - Content script: auto-connect WS, console capture, URL tracking, RPC - Background service worker: token management, screenshots, badge - Popup + side panel with server status, sessions, URL config - CI workflows: build extension, attach .zip to releases - Makefile targets: ext, ext-chrome, ext-firefox, ext-zip - Version bumped to 0.8.0 Assisted-by: GLM-5.1 via Crush <crush@charm.land>
55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
import '../../styles/panel.css';
|
|
import { getServerUrl, setServerUrl, fetchSessions } from '../../lib/config';
|
|
|
|
const $serverStatus = document.getElementById('server-status');
|
|
const $sessionCount = document.getElementById('session-count');
|
|
const $errorCount = document.getElementById('error-count');
|
|
const $btnDashboard = document.getElementById('btn-dashboard');
|
|
const $btnSidepanel = document.getElementById('btn-sidepanel');
|
|
const $serverUrl = document.getElementById('server-url');
|
|
const $btnSaveUrl = document.getElementById('btn-save-url');
|
|
|
|
function dot(color) {
|
|
return `<span class="dot dot-${color}"></span>`;
|
|
}
|
|
|
|
async function refresh() {
|
|
const url = await getServerUrl();
|
|
$serverUrl.value = url;
|
|
$btnDashboard.href = url;
|
|
|
|
try {
|
|
const sessions = await fetchSessions();
|
|
$serverStatus.innerHTML = `${dot('green')} Online`;
|
|
$sessionCount.textContent = sessions.length;
|
|
} catch {
|
|
$serverStatus.innerHTML = `${dot('red')} Offline`;
|
|
$sessionCount.textContent = '—';
|
|
}
|
|
|
|
chrome.runtime.sendMessage({ type: 'get_state' }, (state) => {
|
|
if (chrome.runtime.lastError || !state) return;
|
|
$errorCount.textContent = state.errorCount || 0;
|
|
});
|
|
}
|
|
|
|
$btnSaveUrl.addEventListener('click', async () => {
|
|
const url = $serverUrl.value.trim().replace(/\/$/, '');
|
|
if (url) {
|
|
await setServerUrl(url);
|
|
refresh();
|
|
}
|
|
});
|
|
|
|
$btnSidepanel.addEventListener('click', async () => {
|
|
try {
|
|
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
|
if (tab) {
|
|
chrome.sidePanel.open({ tabId: tab.id });
|
|
window.close();
|
|
}
|
|
} catch {}
|
|
});
|
|
|
|
refresh();
|