/** * Content Script - Debugger UI * * Injects the debugger pane into GitHub Actions job pages and handles * all UI interactions. */ // State let debuggerPane = null; let currentFrameId = 0; let isConnected = false; let replHistory = []; let replHistoryIndex = -1; // HTML escape helper function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } /** * Strip result indicator suffix from step name * e.g., "Run tests [running]" -> "Run tests" */ function stripResultIndicator(name) { return name.replace(/\s*\[(running|success|failure|skipped|cancelled)\]$/i, ''); } /** * Send DAP request to background script */ function sendDapRequest(command, args = {}) { return new Promise((resolve, reject) => { chrome.runtime.sendMessage({ type: 'dap-request', command, args }, (response) => { if (chrome.runtime.lastError) { reject(new Error(chrome.runtime.lastError.message)); } else if (response && response.success) { resolve(response.body); } else { reject(new Error(response?.error || 'Unknown error')); } }); }); } /** * Build map of steps from DOM */ function buildStepMap() { const steps = document.querySelectorAll('check-step'); const map = new Map(); steps.forEach((el, idx) => { map.set(idx, { element: el, number: parseInt(el.dataset.number), name: el.dataset.name, conclusion: el.dataset.conclusion, externalId: el.dataset.externalId, }); }); return map; } /** * Find step element by name */ function findStepByName(stepName) { return document.querySelector(`check-step[data-name="${CSS.escape(stepName)}"]`); } /** * Find step element by number */ function findStepByNumber(stepNumber) { return document.querySelector(`check-step[data-number="${stepNumber}"]`); } /** * Get all step elements */ function getAllSteps() { return document.querySelectorAll('check-step'); } /** * Create the debugger pane HTML */ function createDebuggerPaneHTML() { return `