GitHub Actions
fix: 0 test failures; FileService; real RagService; emergency probe; chat return
4aaae80
Raw
History Blame
3.25 kB
"""M08 β€” UI: HearthNet Gradio dashboard.
The UI's strict rule: it NEVER imports a service module directly.
All data comes via bus.call() or bus introspection APIs.
"""
from __future__ import annotations
from typing import Any
try:
import gradio as gr
HAS_GRADIO = True
except ImportError:
HAS_GRADIO = False
class UiApp:
def __init__(self, bus=None, state_bus=None, config=None, **meta):
self._bus = bus
self._state_bus = state_bus
self._config = config
self._meta = meta
self._demo = None
def build(self) -> Any:
"""Build and return the Gradio Blocks app."""
if not HAS_GRADIO:
raise ImportError("gradio not installed")
from hearthnet.ui.tabs.ask import build_ask_tab
from hearthnet.ui.tabs.chat import build_chat_tab
from hearthnet.ui.tabs.emergency import build_emergency_tab
from hearthnet.ui.tabs.files import build_files_tab
from hearthnet.ui.tabs.getting_started import build_getting_started_tab
from hearthnet.ui.tabs.marketplace import build_marketplace_tab
from hearthnet.ui.tabs.mesh import build_mesh_tab
from hearthnet.ui.tabs.settings import build_settings_tab
# Pull identity from bus when not explicitly provided in meta
if self._bus is not None:
self._meta.setdefault("node_id", getattr(self._bus, "node_id_full", "unknown"))
self._meta.setdefault("community_id", getattr(self._bus, "community_id", "unknown"))
node_id_display = self._meta.get("node_id", "unknown")
display_name = self._meta.get("display_name", node_id_display[:20])
with gr.Blocks(title=f"HearthNet β€” {display_name}") as demo:
gr.Markdown(f"# πŸ”₯ HearthNet β€” {display_name}")
with gr.Row():
gr.HTML(value="<span style='color:green'>● ONLINE</span>")
gr.Markdown(f"Node: `{node_id_display[:40]}`")
gr.Markdown(f"Community: `{self._meta.get('community_id', 'unknown')[:30]}`")
with gr.Tabs():
with gr.Tab("Ask"):
build_ask_tab(self._bus)
with gr.Tab("Chat"):
build_chat_tab(self._bus)
with gr.Tab("Mesh"):
build_mesh_tab(self._bus)
with gr.Tab("Marketplace"):
build_marketplace_tab(self._bus)
with gr.Tab("Files"):
build_files_tab(self._bus)
with gr.Tab("Emergency"):
build_emergency_tab(self._bus, self._state_bus)
with gr.Tab("Settings"):
build_settings_tab(self._config, self._meta, bus=self._bus)
with gr.Tab("Getting Started"):
build_getting_started_tab()
self._demo = demo
return demo
async def shutdown(self) -> None:
if self._demo:
try:
self._demo.close()
except Exception:
pass
def build_ui(bus, state_bus=None, config=None, **meta) -> UiApp:
"""Convenience constructor used by node.py."""
return UiApp(bus=bus, state_bus=state_bus, config=config, **meta)