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>
117 lines
2.7 KiB
JavaScript
117 lines
2.7 KiB
JavaScript
import { fetchToken, fetchSessions, checkServerHealth, getServerUrl } from '../lib/config';
|
|
|
|
export default defineBackground(() => {
|
|
let token = null;
|
|
let wsUrl = null;
|
|
let serverOnline = false;
|
|
let errorCount = 0;
|
|
|
|
async function refreshToken() {
|
|
try {
|
|
const data = await fetchToken();
|
|
token = data.token;
|
|
wsUrl = data.wsUrl;
|
|
serverOnline = true;
|
|
return data;
|
|
} catch {
|
|
serverOnline = false;
|
|
token = null;
|
|
wsUrl = null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function updateBadge() {
|
|
try {
|
|
serverOnline = await checkServerHealth();
|
|
} catch {
|
|
serverOnline = false;
|
|
}
|
|
|
|
if (!serverOnline) {
|
|
chrome.action.setBadgeText({ text: '✕' });
|
|
chrome.action.setBadgeBackgroundColor({ color: '#ff6b6b' });
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const sessions = await fetchSessions();
|
|
const count = sessions.length;
|
|
if (count > 0) {
|
|
chrome.action.setBadgeText({ text: String(count) });
|
|
chrome.action.setBadgeBackgroundColor({ color: '#3aaa61' });
|
|
} else {
|
|
chrome.action.setBadgeText({ text: '○' });
|
|
chrome.action.setBadgeBackgroundColor({ color: '#888' });
|
|
}
|
|
} catch {
|
|
chrome.action.setBadgeText({ text: '?' });
|
|
chrome.action.setBadgeBackgroundColor({ color: '#f5a623' });
|
|
}
|
|
}
|
|
|
|
async function handleScreenshot() {
|
|
try {
|
|
const dataUrl = await chrome.tabs.captureVisibleTab(null, {
|
|
format: 'png',
|
|
quality: 100,
|
|
});
|
|
return { ok: true, data_url: dataUrl };
|
|
} catch (e) {
|
|
return { ok: false, error: 'capture failed: ' + String(e) };
|
|
}
|
|
}
|
|
|
|
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|
if (msg.type === 'get_state') {
|
|
getServerUrl().then((url) => {
|
|
sendResponse({
|
|
serverOnline,
|
|
token,
|
|
wsUrl,
|
|
errorCount,
|
|
serverUrl: url,
|
|
});
|
|
});
|
|
return true;
|
|
}
|
|
|
|
if (msg.type === 'get_token') {
|
|
refreshToken().then((data) => sendResponse(data));
|
|
return true;
|
|
}
|
|
|
|
if (msg.type === 'check_health') {
|
|
checkServerHealth().then((ok) => {
|
|
serverOnline = ok;
|
|
sendResponse({ online: ok });
|
|
});
|
|
return true;
|
|
}
|
|
|
|
if (msg.type === 'screenshot') {
|
|
handleScreenshot().then(sendResponse);
|
|
return true;
|
|
}
|
|
|
|
if (msg.type === 'refresh_badge') {
|
|
updateBadge();
|
|
return false;
|
|
}
|
|
|
|
if (msg.type === 'increment_errors') {
|
|
errorCount++;
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
chrome.alarms.create('muyue-badge', { periodInMinutes: 0.17 });
|
|
chrome.alarms.onAlarm.addListener((alarm) => {
|
|
if (alarm.name === 'muyue-badge') updateBadge();
|
|
});
|
|
|
|
updateBadge();
|
|
});
|