// boot.jsx — заменяет mock-данные из data.jsx реальными с backend // и стартует React. Если API упал/нет данных — остаётся mock (UI всегда жив). async function loadLive() { const endpoints = { TEAM: "/api/agents", ALERTS: "/api/alerts?status=all", EVENTS: "/api/events?limit=200", RULES: "/api/rules", TASKS: "/api/tasks?period=all", }; for (const [name, url] of Object.entries(endpoints)) { try { const r = await fetch(url); if (r.ok) { const data = await r.json(); if (Array.isArray(data) && data.length > 0) { window[name] = data; console.log(`[boot] ${name}: ${data.length} items from ${url}`); } else { console.warn(`[boot] ${name}: API вернул пусто, оставляю mock`); } } else { console.warn(`[boot] ${name}: HTTP ${r.status}, оставляю mock`); } } catch (e) { console.warn(`[boot] ${name}: fetch failed, оставляю mock`, e); } } // AGENT_DOCS — отдельно: 6 запросов на каждую роль try { const roles = ["architect", "coder", "reviewer", "tester", "scout", "workflow-lead"]; const docs = {}; await Promise.all( roles.map(async (role) => { try { const r = await fetch(`/api/instructions/${role}`); if (r.ok) docs[role] = await r.text(); } catch {} }) ); if (Object.keys(docs).length > 0) { window.AGENT_DOCS = { ...window.AGENT_DOCS, ...docs }; console.log(`[boot] AGENT_DOCS: ${Object.keys(docs).length} ролей с сервера`); } } catch (e) { console.warn("[boot] AGENT_DOCS fallback to mock", e); } // Пересчитываем счётчики после замены ALERTS window.ACTIVE_ALERTS = window.ALERTS.filter((a) => a.status === "active"); window.CRITICAL_COUNT = window.ACTIVE_ALERTS.filter((a) => a.severity === "critical").length; window.WARNING_COUNT = window.ACTIVE_ALERTS.filter((a) => a.severity === "warning").length; } (async () => { await loadLive(); const root = ReactDOM.createRoot(document.getElementById("app")); root.render(); })();