()
| 872 | // ---- shell --------------------------------------------------------------- |
| 873 | |
| 874 | function render() { |
| 875 | if (!state) { |
| 876 | $("#app").innerHTML = '<div class="empty"><span class="spin"></span> Loading…</div>'; |
| 877 | return; |
| 878 | } |
| 879 | if (!state.ok) { |
| 880 | $("#app").innerHTML = emptyState("Repo not available", esc(state.error || "Could not read the repository."), btn("Retry", "refresh", {}, { primary: true })); |
| 881 | renderHeader(); |
| 882 | return; |
| 883 | } |
| 884 | renderHeader(); |
| 885 | autopilotRunning = !!(state.autopilot && state.autopilot.running); |
| 886 | const tabs = { overview: overviewTab, readiness: doctorTab, assessment: assessmentTab, plan: planTab, validation: validationTab, tasks: tasksTab, summary: summaryTab }; |
| 887 | let body = ""; |
| 888 | try { |
| 889 | body = autopilotStrip(state); |
| 890 | body += pending ? '<div class="banner"><span class="spin"></span> Sent to the agent: <b>' + esc(pending) + "</b>. Watch the chat; this view refreshes when the turn finishes.</div>" : ""; |
| 891 | body += (tabs[activeTab] || overviewTab)(state); |
| 892 | } catch (e) { |
| 893 | // A tab renderer threw — show the error instead of silently leaving the |
| 894 | // previous tab's content on screen (which looks like a dead click). |
| 895 | body = '<div class="banner banner-red">This view hit an error: ' + esc(e && e.message ? e.message : String(e)) + " " + btn("Reload", "refresh", {}, { primary: true }) + "</div>"; |
| 896 | } |
| 897 | $("#app").innerHTML = body; |
| 898 | } |
| 899 | |
| 900 | function renderHeader() { |
| 901 | const s = state || {}; |
no test coverage detected