#!/usr/bin/env node /** * Build standalone HTML with embedded data * Run: node agent-evolution/scripts/build-standalone.cjs */ const fs = require('fs'); const path = require('path'); const DATA_FILE = path.join(__dirname, '../data/agent-versions.json'); const HTML_FILE = path.join(__dirname, '../index.html'); const OUTPUT_FILE = path.join(__dirname, '../index.standalone.html'); try { // Read data console.log('šŸ“– Reading data from:', DATA_FILE); const data = JSON.parse(fs.readFileSync(DATA_FILE, 'utf-8')); console.log(' Found', Object.keys(data.agents).length, 'agents'); // Read HTML console.log('šŸ“– Reading HTML from:', HTML_FILE); let html = fs.readFileSync(HTML_FILE, 'utf-8'); // Step 1: Replace EMBEDDED_DATA const startMarker = '// Default embedded data (minimal - updated by sync script)'; const endPattern = /"sync_sources":\s*\[[^\]]*\]\s*\}\s*\};/; const startIdx = html.indexOf(startMarker); const endMatch = html.match(endPattern); if (startIdx === -1) { throw new Error('Start marker not found in HTML'); } if (!endMatch) { throw new Error('End pattern not found in HTML'); } const endIdx = endMatch.index + endMatch[0].length + 1; // Create embedded data const embeddedData = `// Embedded data (generated ${new Date().toISOString()}) const EMBEDDED_DATA = ${JSON.stringify(data, null, 2)};`; // Replace the section html = html.substring(0, startIdx) + embeddedData + html.substring(endIdx); // Step 2: Replace entire init function // Find the init function start and end const initStartPattern = /\/\/ Initialize\s*\n\s*async function init\(\) \{/; const initStartMatch = html.match(initStartPattern); if (initStartMatch) { const initStartIdx = initStartMatch.index; // Find matching closing brace (count opening and closing) let braceCount = 0; let inFunction = false; let initEndIdx = initStartIdx; for (let i = initStartIdx; i < html.length; i++) { if (html[i] === '{') { braceCount++; inFunction = true; } else if (html[i] === '}') { braceCount--; if (inFunction && braceCount === 0) { initEndIdx = i + 1; break; } } } // New init function const newInit = `// Initialize async function init() { // Use embedded data directly (works with file://) agentData = EMBEDDED_DATA; try { document.getElementById('lastSync').textContent = formatDate(agentData.lastUpdated); document.getElementById('agentCount').textContent = agentData.evolution_metrics.total_agents + ' agents'; document.getElementById('historyCount').textContent = agentData.evolution_metrics.agents_with_history + ' with history'; if (agentData.evolution_metrics.total_agents === 0) { document.getElementById('lastSync').textContent = 'No data - run sync:evolution'; return; } renderOverview(); renderAllAgents(); renderTimeline(); renderRecommendations(); renderMatrix(); } catch (error) { console.error('Failed to render dashboard:', error); document.getElementById('lastSync').textContent = 'Error rendering data'; } }`; html = html.substring(0, initStartIdx) + newInit + html.substring(initEndIdx); } // Write output fs.writeFileSync(OUTPUT_FILE, html); console.log('\nāœ… Built standalone dashboard'); console.log(' Output:', OUTPUT_FILE); console.log(' Agents:', Object.keys(data.agents).length); console.log(' Size:', (fs.statSync(OUTPUT_FILE).size / 1024).toFixed(1), 'KB'); console.log('\nšŸ“Š Open in browser:'); console.log(' Windows: start agent-evolution\\index.standalone.html'); console.log(' macOS: open agent-evolution/index.standalone.html'); console.log(' Linux: xdg-open agent-evolution/index.standalone.html'); } catch (error) { console.error('āŒ Error:', error.message); process.exit(1); }