Cascade-Hyperlattice-v2 / src /streamlit_app_grid.py
tostido's picture
Initial commit: CASCADE Hyperlattice mobile-friendly interactive 3D visualization
61247fd
"""
CASCADE Hyperlattice - Interactive Grid Dashboard
Quine agent swarms navigating a 3D decision lattice with null gates.
๐Ÿ”ฎ GLASS BOX: Everything is observable. No hidden state.
Features:
- 3D Plotly visualization with click-to-select
- Draggable, resizable grid of data panels
- All data visible simultaneously (no tabs)
- Brady Bunch style equilateral cells
"""
import streamlit as st
import plotly.graph_objects as go
import numpy as np
import time
import colorsys
import json
from streamlit_elements import elements, mui, html, dashboard, sync, lazy
from lattice import Hyperlattice
from swarm import QuineSwarm
from ipfs_sync import CollectiveMemory, SyncManager
from cascade_bridge import CascadeBridge
from champion_loader import (
get_champion_info, load_champion_module,
get_champion_diagnostics, get_replicated_agents_info, get_download_status
)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# GPU DETECTION
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
try:
import torch
TORCH_AVAILABLE = True
GPU_AVAILABLE = torch.cuda.is_available()
GPU_NAME = torch.cuda.get_device_name(0) if GPU_AVAILABLE else None
GPU_MEMORY = torch.cuda.get_device_properties(0).total_memory // (1024**3) if GPU_AVAILABLE else 0
except ImportError:
TORCH_AVAILABLE = False
GPU_AVAILABLE = False
GPU_NAME = None
GPU_MEMORY = 0
# CASCADE
try:
from cascade import Tracer, CausationGraph, sdk_observe
CASCADE_AVAILABLE = True
except ImportError:
CASCADE_AVAILABLE = False
sdk_observe = None
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# PAGE CONFIG
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
st.set_page_config(
page_title="CASCADE Hyperlattice",
page_icon="๐ŸŒŒ",
layout="wide"
)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# THEMES
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
THEMES = {
"neon_vampire": {
"name": "๐Ÿง› Neon Vampire",
"bg": "rgba(10,5,15,1)",
"paper": "rgba(15,8,20,1)",
"edges": "rgba(120,0,180,0.4)",
"null_gates": "rgba(255,0,80,1)",
"primary": "#7800b4",
"card_bg": "rgba(15,8,20,0.95)",
},
"cyber_blue": {
"name": "๐Ÿ’Ž Cyber Blue",
"bg": "rgba(5,10,20,1)",
"paper": "rgba(8,15,30,1)",
"edges": "rgba(0,150,255,0.4)",
"null_gates": "rgba(255,100,0,1)",
"primary": "#0096ff",
"card_bg": "rgba(8,15,30,0.95)",
},
"matrix_green": {
"name": "๐Ÿธ Matrix Green",
"bg": "rgba(0,5,0,1)",
"paper": "rgba(0,10,0,1)",
"edges": "rgba(0,255,0,0.3)",
"null_gates": "rgba(255,0,0,1)",
"primary": "#00ff00",
"card_bg": "rgba(0,10,0,0.95)",
},
}
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# SESSION STATE
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
def init_session_state():
if 'initialized' not in st.session_state:
st.session_state.initialized = False
st.session_state.lattice = None
st.session_state.swarm = None
st.session_state.cascade = None
st.session_state.step_count = 0
st.session_state.events = []
st.session_state.theme = "neon_vampire"
st.session_state.selected_agent = None
st.session_state.grid_layout = None
init_session_state()
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# DEFAULT GRID LAYOUT
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
DEFAULT_LAYOUT = [
# Row 1 - Main panels (wider)
dashboard.Item("champion", 0, 0, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("agent", 3, 0, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("lineages", 6, 0, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("provenance", 9, 0, 3, 2, isDraggable=True, isResizable=True),
# Row 2 - Secondary panels
dashboard.Item("traits", 0, 2, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("capabilities", 3, 2, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("stats", 6, 2, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("events", 9, 2, 3, 2, isDraggable=True, isResizable=True),
# Row 3 - Additional panels
dashboard.Item("hold", 0, 4, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("architecture", 3, 4, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("system", 6, 4, 3, 2, isDraggable=True, isResizable=True),
dashboard.Item("download", 9, 4, 3, 2, isDraggable=True, isResizable=True),
]
if st.session_state.grid_layout is None:
st.session_state.grid_layout = DEFAULT_LAYOUT
def handle_layout_change(updated_layout):
st.session_state.grid_layout = updated_layout
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# LINEAGE COLOR SYSTEM
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
def get_lineage_color(root_id: str, generation: int, fitness: float, max_gen: int = 10):
hue = (hash(root_id) % 360) / 360.0
saturation = max(0.3, 1.0 - (generation / max(max_gen, 1)) * 0.7)
lightness = 0.4 + min(1.0, max(0.0, fitness / 10.0)) * 0.5
r, g, b = colorsys.hls_to_rgb(hue, lightness, saturation)
return f'rgb({int(r*255)},{int(g*255)},{int(b*255)})'
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# SIMULATION
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
def init_simulation(size=6, agents=5, gates=4):
st.session_state.lattice = Hyperlattice(size=size)
st.session_state.lattice.add_null_gates(gates)
st.session_state.swarm = QuineSwarm(st.session_state.lattice, num_agents=agents)
st.session_state.cascade = CascadeBridge()
st.session_state.step_count = 0
st.session_state.events = ["๐Ÿš€ Simulation initialized"]
st.session_state.initialized = True
load_champion_module()
def step():
if not st.session_state.initialized:
return
st.session_state.swarm.step()
st.session_state.step_count += 1
if st.session_state.cascade:
st.session_state.cascade.log_step(st.session_state.step_count, st.session_state.swarm)
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# 3D PLOT
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
def create_plot():
theme = THEMES[st.session_state.theme]
fig = go.Figure()
if not st.session_state.initialized:
fig.update_layout(
scene=dict(bgcolor=theme['bg']),
paper_bgcolor=theme['paper'],
height=400
)
return fig
lattice = st.session_state.lattice
swarm = st.session_state.swarm
# Null gates
null_pos = np.array([list(ng) for ng in lattice.null_gates]) if lattice.null_gates else np.array([])
if len(null_pos) > 0:
fig.add_trace(go.Scatter3d(
x=null_pos[:, 0], y=null_pos[:, 1], z=null_pos[:, 2],
mode='markers',
marker=dict(size=12, color=theme['null_gates'], symbol='x', opacity=0.8),
name='Null Gates'
))
# Agents
lineage_data = swarm.get_agent_lineage_data()
if lineage_data:
max_gen = max(d['generation'] for d in lineage_data.values()) if lineage_data else 1
max_gen = max(max_gen, 1)
agent_ids = list(lineage_data.keys())
ax = [lineage_data[aid]['position'][0] for aid in agent_ids]
ay = [lineage_data[aid]['position'][1] for aid in agent_ids]
az = [lineage_data[aid]['position'][2] for aid in agent_ids]
colors = []
sizes = []
hover_texts = []
for aid in agent_ids:
d = lineage_data[aid]
color = get_lineage_color(d['root_lineage'], d['generation'], d['fitness'], max_gen)
colors.append(color)
sizes.append(14 - min(d['generation'], 8))
hover_texts.append(
f"<b>{aid}</b><br>Gen: {d['generation']}<br>Fit: {d['fitness']:.2f}"
)
# Originals
orig_idx = [i for i, aid in enumerate(agent_ids) if lineage_data[aid]['generation'] == 0]
if orig_idx:
fig.add_trace(go.Scatter3d(
x=[ax[i] for i in orig_idx],
y=[ay[i] for i in orig_idx],
z=[az[i] for i in orig_idx],
mode='markers',
marker=dict(
size=[sizes[i] for i in orig_idx],
color=[colors[i] for i in orig_idx],
symbol='diamond',
line=dict(width=2, color='white')
),
hoverinfo='text',
text=[hover_texts[i] for i in orig_idx],
customdata=[agent_ids[i] for i in orig_idx],
name='Originals'
))
# Replicants
rep_idx = [i for i, aid in enumerate(agent_ids) if lineage_data[aid]['generation'] > 0]
if rep_idx:
fig.add_trace(go.Scatter3d(
x=[ax[i] for i in rep_idx],
y=[ay[i] for i in rep_idx],
z=[az[i] for i in rep_idx],
mode='markers',
marker=dict(
size=[sizes[i] for i in rep_idx],
color=[colors[i] for i in rep_idx],
symbol='circle',
opacity=0.8
),
hoverinfo='text',
text=[hover_texts[i] for i in rep_idx],
customdata=[agent_ids[i] for i in rep_idx],
name='Replicants'
))
fig.update_layout(
scene=dict(
xaxis=dict(visible=False, backgroundcolor=theme['bg']),
yaxis=dict(visible=False, backgroundcolor=theme['bg']),
zaxis=dict(visible=False, backgroundcolor=theme['bg']),
bgcolor=theme['bg'],
camera=dict(eye=dict(
x=1.5 * np.cos(st.session_state.step_count * 0.03),
y=1.5 * np.sin(st.session_state.step_count * 0.03),
z=0.8
))
),
paper_bgcolor=theme['paper'],
margin=dict(l=0, r=0, t=0, b=0),
height=350,
showlegend=False
)
return fig
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# PANEL CARD WRAPPER
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
def card_style(border_color):
return {
"height": "100%",
"display": "flex",
"flexDirection": "column",
"bgcolor": "rgba(15,8,20,0.95)",
"border": f"1px solid {border_color}",
"borderRadius": "4px",
"overflow": "hidden",
"&:hover": {"boxShadow": f"0 0 15px {border_color}40"},
}
def header_style():
return {
"display": "flex",
"justifyContent": "space-between",
"alignItems": "center",
"borderBottom": "1px solid rgba(255,255,255,0.1)",
"p": 0.5,
"cursor": "grab",
"bgcolor": "rgba(0,0,0,0.3)",
}
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# UI
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
st.title("๐ŸŒŒ CASCADE Hyperlattice")
st.caption("๐Ÿ”ฎ GLASS BOX AI - Every decision is transparent and drillable")
# Sidebar
with st.sidebar:
st.header("๐ŸŽจ Theme")
theme = st.selectbox("Theme", list(THEMES.keys()), format_func=lambda x: THEMES[x]['name'])
if theme != st.session_state.theme:
st.session_state.theme = theme
st.divider()
st.header("โš™๏ธ Setup")
size = st.slider("Lattice Size", 3, 10, 6)
agents = st.slider("Agents", 1, 10, 5)
gates = st.slider("Null Gates", 2, 10, 4)
if st.button("๐Ÿ”„ Initialize", type="primary", use_container_width=True):
init_simulation(size, agents, gates)
st.divider()
st.header("โ–ถ๏ธ Animation")
speed = st.slider("Speed", 1, 20, 8)
c1, c2 = st.columns(2)
play = c1.button("โ–ถ๏ธ", use_container_width=True)
stop = c2.button("โน๏ธ", use_container_width=True)
if st.button("โšก Step", use_container_width=True):
step()
if st.button("๐Ÿ”€ Reset Layout", use_container_width=True):
st.session_state.grid_layout = DEFAULT_LAYOUT
# Stats
st.divider()
if st.session_state.initialized:
stats = st.session_state.swarm.get_swarm_stats()
st.metric("Step", st.session_state.step_count)
st.metric("Agents", stats['num_agents'])
if GPU_AVAILABLE:
st.success(f"๐Ÿš€ {GPU_NAME[:20]}...")
else:
st.info("๐Ÿ’ป CPU")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# MAIN CONTENT
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# Auto-init
if not st.session_state.initialized:
init_simulation()
# 3D Graph (native Streamlit for click events)
st.subheader("๐ŸŒ Lattice")
selection = st.plotly_chart(
create_plot(),
use_container_width=True,
key="main_plot",
on_select="rerun",
selection_mode="points"
)
# Handle click
if selection and hasattr(selection, 'selection') and selection.selection:
points = selection.selection.get('points', [])
if points:
clicked = points[0]
if 'customdata' in clicked and clicked['customdata']:
agent_id = clicked['customdata'][0] if isinstance(clicked['customdata'], list) else clicked['customdata']
if agent_id != st.session_state.selected_agent:
st.session_state.selected_agent = agent_id
st.rerun()
# Selected agent indicator
if st.session_state.selected_agent:
st.success(f"๐ŸŽฏ Selected: **{st.session_state.selected_agent}**")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# GRID DASHBOARD
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
st.markdown("---")
st.subheader("๐Ÿ“Š Data Grid")
st.caption("Drag panels to reorder โ€ข Resize by dragging edges โ€ข All data visible")
# Gather all data
diagnostics = get_champion_diagnostics()
identity = diagnostics.get('identity', {})
arch = diagnostics.get('architecture', {})
caps = diagnostics.get('capabilities', {})
traits = diagnostics.get('traits', {})
hold = diagnostics.get('hold_system', {})
dl_status = diagnostics.get('download', {})
agent_data = None
if st.session_state.selected_agent and st.session_state.initialized:
lineage_data = st.session_state.swarm.get_agent_lineage_data()
agent_data = lineage_data.get(st.session_state.selected_agent)
lineages = {}
if st.session_state.initialized:
agents_info = get_replicated_agents_info(st.session_state.swarm)
for a in agents_info:
root = a['root_lineage']
if root not in lineages:
lineages[root] = []
lineages[root].append(a)
receipt = {}
if st.session_state.cascade:
receipt = st.session_state.cascade.get_session_receipt()
stats = {}
if st.session_state.initialized:
stats = st.session_state.swarm.get_swarm_stats()
events = st.session_state.events
# Custom CSS
st.markdown("""
<style>
.react-grid-item.react-draggable-dragging {
box-shadow: 0 0 30px rgba(120, 0, 180, 0.8);
z-index: 1000;
opacity: 0.95;
}
.react-grid-item.react-grid-placeholder {
background: rgba(120, 0, 180, 0.4) !important;
border: 2px dashed rgba(255, 255, 255, 0.6);
border-radius: 4px;
}
.react-grid-item > .react-resizable-handle {
background: rgba(120, 0, 180, 0.6);
width: 12px;
height: 12px;
}
</style>
""", unsafe_allow_html=True)
# Render grid
with elements("data_grid"):
with dashboard.Grid(
st.session_state.grid_layout,
onLayoutChange=handle_layout_change,
cols=12,
rowHeight=60,
compactType="vertical",
margin=[4, 4],
):
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# CHAMPION
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="champion", sx=card_style("rgba(255,215,0,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ† Champion", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.7rem"}):
mui.Typography(f"Gen: {identity.get('generation', '?')}", variant="body2")
mui.Typography(f"Brain: {identity.get('brain_type', '?')}", variant="body2")
mui.Typography(f"Fitness: {identity.get('fitness', 0):.4f}", variant="body2")
mui.Typography(f"Quine: {identity.get('quine_hash', '?')[:20]}...", variant="caption", sx={"fontFamily": "monospace"})
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# AGENT
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="agent", sx=card_style("rgba(0,200,255,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ‘ค Agent", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.7rem"}):
if agent_data:
gen = agent_data.get('generation', 0)
prefix = "โ—† Original" if gen == 0 else f"โ— Replicant Gen {gen}"
mui.Typography(prefix, variant="body2", sx={"fontWeight": "bold"})
mui.Typography(f"Fitness: {agent_data.get('fitness', 0):.3f}", variant="body2")
mui.Typography(f"Children: {agent_data.get('num_children', 0)}", variant="body2")
mui.Typography(f"Root: {agent_data.get('root_lineage', 'self')[:12]}...", variant="caption")
mui.Typography(f"Hash: {agent_data.get('quine_hash', '?')[:16]}...", variant="caption", sx={"fontFamily": "monospace"})
else:
mui.Typography("Click agent in graph", variant="caption", color="text.secondary")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# LINEAGES
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="lineages", sx=card_style("rgba(0,255,100,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿงฌ Lineages", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.65rem"}):
if lineages:
for root_id, members in list(lineages.items())[:4]:
mui.Typography(f"๐ŸŒณ {root_id[:10]}... ({len(members)})", variant="caption", sx={"fontWeight": "bold"})
for m in members[:2]:
prefix = "โ—†" if m.get('is_original') else "โ—"
mui.Typography(f" {prefix} Gen{m.get('generation', 0)} Fit:{m.get('fitness', 0):.2f}", variant="caption")
else:
mui.Typography("No lineages", variant="caption")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# PROVENANCE
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="provenance", sx=card_style("rgba(255,100,0,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ”— Provenance", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.7rem"}):
mui.Typography(f"Decisions: {receipt.get('total_decisions', 0)}", variant="body2")
mui.Typography(f"Agents: {receipt.get('total_agents', 0)}", variant="body2")
mui.Typography(f"Ghost Tape: {receipt.get('ghost_tape_events', 0)}", variant="body2")
mui.Typography(f"Merkle: {receipt.get('merkle_root', 'N/A')[:16]}...", variant="caption", sx={"fontFamily": "monospace"})
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# TRAITS
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="traits", sx=card_style("rgba(255,0,200,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿงฌ Traits", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.65rem"}):
if traits:
for k, v in list(traits.items())[:6]:
val = f"{v:.4f}" if isinstance(v, float) else str(v)
mui.Typography(f"{k}: {val}", variant="caption")
else:
mui.Typography("No traits", variant="caption")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# CAPABILITIES
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="capabilities", sx=card_style("rgba(100,100,255,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("โš™๏ธ Capabilities", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.65rem"}):
if caps:
for k, v in list(caps.items())[:8]:
icon = "โœ…" if v else "โŒ"
mui.Typography(f"{icon} {k}", variant="caption")
else:
mui.Typography("No caps", variant="caption")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# STATS
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="stats", sx=card_style("rgba(0,255,255,0.5)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ“ˆ Stats", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.7rem"}):
mui.Typography(f"Step: {st.session_state.step_count}", variant="body2")
mui.Typography(f"Agents: {stats.get('num_agents', 0)}", variant="body2")
mui.Typography(f"Max Gen: {stats.get('max_generation', 0)}", variant="body2")
mui.Typography(f"Avg Fit: {stats.get('avg_fitness', 0):.3f}", variant="body2")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# EVENTS
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="events", sx=card_style("rgba(200,200,200,0.3)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ“œ Events", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.6rem"}):
for event in reversed(events[-8:]):
mui.Typography(event, variant="caption", sx={"display": "block"})
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# HOLD SYSTEM
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="hold", sx=card_style("rgba(255,0,0,0.4)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ›‘ HOLD", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.7rem"}):
if hold:
mui.Typography(f"Enabled: {'โœ…' if hold.get('enabled') else 'โŒ'}", variant="body2")
mui.Typography(f"Timeout: {hold.get('timeout', 30)}s", variant="body2")
mui.Typography(f"Holds: {hold.get('hold_count', 0)}", variant="body2")
mui.Typography(f"Overrides: {hold.get('override_count', 0)}", variant="body2")
else:
mui.Typography("No HOLD data", variant="caption")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# ARCHITECTURE
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="architecture", sx=card_style("rgba(180,0,255,0.4)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ—๏ธ Arch", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.65rem"}):
mui.Typography(f"Brain: {arch.get('brain_type', 'N/A')}", variant="caption")
mui.Typography(f"Hidden: {arch.get('hidden_size', 'N/A')}", variant="caption")
mui.Typography(f"LoRA: {arch.get('lora_rank', 'N/A')}", variant="caption")
mui.Typography(f"Latent: {arch.get('latent_dim', 'N/A')}", variant="caption")
mui.Typography(f"RSSM: {'โœ…' if arch.get('has_rssm') else 'โŒ'}", variant="caption")
mui.Typography(f"Dreamer: {'โœ…' if arch.get('has_dreamer') else 'โŒ'}", variant="caption")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# SYSTEM
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="system", sx=card_style("rgba(50,200,50,0.4)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ–ฅ๏ธ System", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.7rem"}):
if GPU_AVAILABLE:
mui.Typography(f"๐Ÿš€ {GPU_NAME[:18]}...", variant="body2")
mui.Typography(f"VRAM: {GPU_MEMORY}GB", variant="caption")
else:
mui.Typography("๐Ÿ’ป CPU Mode", variant="body2")
mui.Typography(f"PyTorch: {'โœ…' if TORCH_AVAILABLE else 'โŒ'}", variant="caption")
mui.Typography(f"CASCADE: {'โœ…' if CASCADE_AVAILABLE else 'โŒ'}", variant="caption")
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
# DOWNLOAD
# โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
with mui.Card(key="download", sx=card_style("rgba(0,150,255,0.4)")):
with mui.Box(sx=header_style()):
mui.Typography("๐Ÿ“ฅ Download", sx={"fontSize": "0.8rem", "fontWeight": "bold"})
with mui.CardContent(sx={"flex": 1, "p": 0.5, "overflow": "auto", "fontSize": "0.65rem"}):
if dl_status.get('downloaded'):
mui.Typography("โœ… Champion loaded", variant="body2", color="success.main")
mui.Typography(f"Repo: {dl_status.get('repo', 'HF')}", variant="caption")
mui.Typography(f"File: {dl_status.get('filename', 'N/A')[:20]}...", variant="caption")
else:
mui.Typography("โŒ Not downloaded", variant="body2", color="error.main")
if dl_status.get('error'):
mui.Typography(f"Error: {dl_status['error'][:30]}...", variant="caption")
# Animation loop
if play:
for _ in range(100):
step()
time.sleep(1.0 / speed)
st.rerun()