evolva-operator / app.py
Pippinlitli's picture
Deploy Evolva operator dashboard - fetches CURRENT_STATE.md from GitHub
50e398f verified
Raw
History Blame Contribute Delete
9.62 kB
"""
Evolva Operator Dashboard
Fetches CURRENT_STATE.md from GitHub and displays:
- Current sprint/phase
- Test pass/fail counts
- Recent session count
- Status indicator (GREEN/YELLOW/RED)
"""
import gradio as gr
import requests
import re
import json
from datetime import datetime, timezone
# ─── GitHub Configuration ─────────────────────────────────────────────────────
GITHUB_RAW_URLS = [
"https://raw.githubusercontent.com/Gudmundur76/manus-persistent-drive/main/CURRENT_STATE.md",
"https://raw.githubusercontent.com/Gudmundur76/ttruthdesk-platform/main/CURRENT_STATE.md",
"https://raw.githubusercontent.com/Gudmundur76/manus-persistent-drive/main/docs/CURRENT_STATE.md",
]
# ─── Fetch & Parse CURRENT_STATE.md ──────────────────────────────────────────
def fetch_current_state():
"""Fetch CURRENT_STATE.md from GitHub, trying multiple known paths."""
content = None
source_url = None
for url in GITHUB_RAW_URLS:
try:
resp = requests.get(url, timeout=10)
if resp.status_code == 200:
content = resp.text
source_url = url
break
except Exception:
continue
return content, source_url
def parse_state(content: str) -> dict:
"""Parse key metrics from CURRENT_STATE.md markdown."""
state = {
"sprint": "Unknown",
"phase": "Unknown",
"tests_pass": 0,
"tests_fail": 0,
"tests_total": 0,
"sessions": 0,
"status": "YELLOW",
"last_updated": "Unknown",
"raw_content": content
}
if not content:
return state
# Sprint/phase detection
sprint_match = re.search(r'[Ss]print[\s#:]*(\d+)', content)
if sprint_match:
state["sprint"] = f"Sprint {sprint_match.group(1)}"
phase_match = re.search(r'[Pp]hase[\s#:]*(\d+|[A-Za-z]+)', content)
if phase_match:
state["phase"] = f"Phase {phase_match.group(1)}"
# Test counts
pass_match = re.search(r'[Pp]ass(?:ing|ed)?[\s:]*(\d+)', content)
fail_match = re.search(r'[Ff]ail(?:ing|ed)?[\s:]*(\d+)', content)
total_match = re.search(r'[Tt]otal[\s:]*(\d+)\s*[Tt]ests?', content)
if pass_match:
state["tests_pass"] = int(pass_match.group(1))
if fail_match:
state["tests_fail"] = int(fail_match.group(1))
if total_match:
state["tests_total"] = int(total_match.group(1))
elif state["tests_pass"] or state["tests_fail"]:
state["tests_total"] = state["tests_pass"] + state["tests_fail"]
# Session count
session_match = re.search(r'[Ss]ession(?:s)?[\s:]*(\d+)', content)
if session_match:
state["sessions"] = int(session_match.group(1))
# Status detection
if re.search(r'\bGREEN\b', content):
state["status"] = "GREEN"
elif re.search(r'\bRED\b', content):
state["status"] = "RED"
elif re.search(r'\bYELLOW\b', content):
state["status"] = "YELLOW"
# Last updated
date_match = re.search(r'(?:[Ll]ast [Uu]pdated|[Dd]ate)[\s:]*([0-9]{4}-[0-9]{2}-[0-9]{2})', content)
if date_match:
state["last_updated"] = date_match.group(1)
return state
def get_status_html(status: str) -> str:
colors = {
"GREEN": ("#28a745", "🟒", "All systems operational"),
"YELLOW": ("#ffc107", "🟑", "In progress / attention needed"),
"RED": ("#dc3545", "πŸ”΄", "Blocked / critical issues"),
}
color, emoji, label = colors.get(status, ("#6c757d", "βšͺ", "Unknown"))
return f"""
<div style='
padding: 16px 24px;
background: {color}22;
border: 2px solid {color};
border-radius: 12px;
text-align: center;
font-size: 1.4em;
font-weight: bold;
color: {color};
'>
{emoji} {status} β€” {label}
</div>
"""
def get_metrics_html(state: dict) -> str:
pass_pct = (state["tests_pass"] / state["tests_total"] * 100) if state["tests_total"] > 0 else 0
bar_color = "#28a745" if pass_pct >= 80 else "#ffc107" if pass_pct >= 50 else "#dc3545"
return f"""
<div style='display:grid; grid-template-columns:1fr 1fr 1fr 1fr; gap:12px; margin:12px 0;'>
<div style='background:#f8f9fa; border-radius:10px; padding:14px; text-align:center; border:1px solid #dee2e6;'>
<div style='font-size:0.8em; color:#6c757d; text-transform:uppercase; letter-spacing:1px;'>Sprint</div>
<div style='font-size:1.5em; font-weight:bold; color:#0f3460;'>{state["sprint"]}</div>
</div>
<div style='background:#f8f9fa; border-radius:10px; padding:14px; text-align:center; border:1px solid #dee2e6;'>
<div style='font-size:0.8em; color:#6c757d; text-transform:uppercase; letter-spacing:1px;'>Phase</div>
<div style='font-size:1.5em; font-weight:bold; color:#0f3460;'>{state["phase"]}</div>
</div>
<div style='background:#f8f9fa; border-radius:10px; padding:14px; text-align:center; border:1px solid #dee2e6;'>
<div style='font-size:0.8em; color:#6c757d; text-transform:uppercase; letter-spacing:1px;'>Tests</div>
<div style='font-size:1.1em; font-weight:bold;'>
<span style='color:#28a745;'>βœ“ {state["tests_pass"]}</span>
&nbsp;/&nbsp;
<span style='color:#dc3545;'>βœ— {state["tests_fail"]}</span>
</div>
<div style='background:#dee2e6; border-radius:4px; height:6px; margin-top:6px;'>
<div style='background:{bar_color}; width:{pass_pct:.0f}%; height:100%; border-radius:4px;'></div>
</div>
</div>
<div style='background:#f8f9fa; border-radius:10px; padding:14px; text-align:center; border:1px solid #dee2e6;'>
<div style='font-size:0.8em; color:#6c757d; text-transform:uppercase; letter-spacing:1px;'>Sessions</div>
<div style='font-size:1.5em; font-weight:bold; color:#0f3460;'>{state["sessions"]}</div>
</div>
</div>
"""
# ─── Main Dashboard Function ──────────────────────────────────────────────────
def load_dashboard():
"""Fetch and render the full operator dashboard."""
fetch_time = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
content, source_url = fetch_current_state()
if content is None:
# Graceful fallback when CURRENT_STATE.md is not found
status_html = get_status_html("YELLOW")
metrics_html = """
<div style='padding:16px; background:#fff3cd; border:1px solid #ffc107; border-radius:8px; text-align:center;'>
<b>⚠️ CURRENT_STATE.md not found</b><br>
Checked paths:<br>
<small>
β€’ github.com/Gudmundur76/manus-persistent-drive/main/CURRENT_STATE.md<br>
β€’ github.com/Gudmundur76/ttruthdesk-platform/main/CURRENT_STATE.md
</small><br><br>
The file will be created as part of the Evolva deployment pipeline.
</div>
"""
raw_md = "CURRENT_STATE.md not yet available in the GitHub repository.\n\nThis file will be created automatically by the Evolva CI pipeline."
source_info = "Source: Not found (file pending)"
else:
state = parse_state(content)
status_html = get_status_html(state["status"])
metrics_html = get_metrics_html(state)
raw_md = content
source_info = f"Source: [{source_url}]({source_url})"
header_html = f"""
<div style='
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
padding: 20px 24px; border-radius: 12px; margin-bottom: 16px; color: white;
'>
<h2 style='margin:0; color:white;'>🧬 Evolva β€” Operator Dashboard</h2>
<p style='margin:4px 0 0 0; color:#a0c4ff; font-size:0.9em;'>
Last fetched: {fetch_time} &nbsp;|&nbsp; {source_info}
</p>
</div>
"""
return header_html, status_html, metrics_html, raw_md
# ─── Gradio UI ────────────────────────────────────────────────────────────────
with gr.Blocks(title="Evolva Operator Dashboard", theme=gr.themes.Soft()) as demo:
with gr.Row():
refresh_btn = gr.Button("πŸ”„ Refresh Dashboard", variant="primary", size="lg")
header_out = gr.HTML()
status_out = gr.HTML(label="System Status")
metrics_out = gr.HTML(label="Key Metrics")
with gr.Accordion("πŸ“„ Raw CURRENT_STATE.md", open=False):
raw_out = gr.Markdown()
gr.Markdown("""
---
**Links:**
[Model Repo](https://huggingface.co/Pippinlitli/evolva-molecular-slm) |
[Inference API](https://huggingface.co/spaces/Pippinlitli/evolva-inference) |
[Frontend Demo](https://huggingface.co/spaces/Pippinlitli/evolva-frontend) |
[GitHub: manus-persistent-drive](https://github.com/Gudmundur76/manus-persistent-drive)
""")
# Auto-load on startup
demo.load(load_dashboard, outputs=[header_out, status_out, metrics_out, raw_out])
refresh_btn.click(load_dashboard, outputs=[header_out, status_out, metrics_out, raw_out])
if __name__ == "__main__":
demo.launch()