Saltar a contenido

Guía de Extensión HUD

Esta guía te lleva a través de agregar un panel personalizado al HUD. Cada nivel construye sobre el anterior.

Lee el doc de Arquitectura primero

Esta guía asume que entiendes el flujo de datos del HUD y el contrato de panel. Lee Arquitectura del HUD antes de continuar.

Nivel 1 — Panel Hello World

Crea un archivo de panel con la estructura mínima requerida:

# raise_cli/hud/panels/my_panel.py
from textual.app import ComposeResult
from textual.widgets import Static, Widget


class MyPanel(Widget):
    def compose(self) -> ComposeResult:
        yield Static("Hello from MyPanel", id="my-content")

    def update_data(self, **kwargs) -> None:
        pass  # recibe pushes de datos pero los ignora por ahora

Conéctalo en app.py:

# En RaiseHUD.compose(), agrega un nuevo TabPane:
with TabPane("My Panel", id="tab-my-panel"):
    yield MyPanel()

Ejecuta rai hud — tu pestaña aparece en el HUD con texto estático.

Nivel 2 — Panel Basado en Datos

Sobreescribe update_data para consumir los kwargs enviados por HUDDataManager:

class MyPanel(Widget):
    def compose(self) -> ComposeResult:
        yield Static("—", id="my-content")

    def update_data(self, **kwargs) -> None:
        pipeline_runs = kwargs.get("pipeline_runs", [])
        count = len(pipeline_runs)
        self.query_one("#my-content", Static).update(f"{count} pipeline runs")

Registra la llamada en el método _push_session_data de app.py:

def _push_session_data(self) -> None:
    # ... llamadas a paneles existentes ...
    try:
        my_panel = self.query_one(MyPanel)
        my_panel.update_data(pipeline_runs=self._pipeline_runs)
    except Exception:
        logger.debug("MyPanel not ready")

Ahora tu panel se actualiza cada vez que corre _poll_fast (cada 5 segundos).

Nivel 3 — Panel Controlado por Polling

Si tu panel necesita datos que HUDDataManager aún no carga, agrega la llamada de carga en _poll_fast (para datos en tiempo real) o _poll_slow (para agregaciones):

def _poll_fast(self) -> None:
    if self._data is None:
        return
    # ... cargas existentes ...
    self._my_data = self._data.load_pipeline_runs(limit=5)  # ejemplo
    try:
        my_panel = self.query_one(MyPanel)
        my_panel.update_data(pipeline_runs=self._my_data)
    except Exception:
        logger.debug("MyPanel not ready")

Cómo elegir el intervalo correcto:

Intervalo Método Úsalo cuando
5 s _poll_fast Los datos cambian frecuentemente (sesiones, runs, señales)
30 s _poll_slow Agregaciones costosas o datos que cambian lentamente (KPIs, tendencias)

Tu panel ahora es un participante completo en el ciclo de polling del HUD.