hermes-hub/src/antigravity_provider/router/ui/views/health_view.py
2026-08-21 08:41:50 +07:00

89 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Keyed system-health view using only the supplied snapshot."""
from __future__ import annotations
from typing import Any, Callable, Dict, Optional
import customtkinter as ctk
from antigravity_provider.router.state_store import HubSnapshot
from antigravity_provider.router.ui.components import HubCard, SectionHeader, StatusBadge
from antigravity_provider.router.ui.theme import Theme
class HealthProfileRow(HubCard):
def __init__(self, master: Any):
super().__init__(master, corner_radius=Theme.RADIUS_SM, border_color=Theme.BORDER_SUBTLE)
self.identity = ctk.CTkLabel(self, text="", font=Theme.font_body_bold(), text_color=Theme.TEXT_PRIMARY)
self.identity.grid(row=0, column=0, padx=Theme.CARD_PAD_X, pady=Theme.SPACE_SM, sticky="w")
self.models = ctk.CTkLabel(self, text="", font=Theme.font_caption(), text_color=Theme.TEXT_MUTED)
self.models.grid(row=0, column=1, padx=Theme.CARD_PAD_X, pady=Theme.SPACE_SM, sticky="w")
self.status = StatusBadge(self, "not_tested")
self.status.grid(row=0, column=2, padx=Theme.CARD_PAD_X, pady=Theme.SPACE_SM, sticky="e")
self.grid_columnconfigure(0, weight=2)
self.grid_columnconfigure(1, weight=3)
self.grid_columnconfigure(2, weight=1)
def update_profile(self, profile: Any) -> None:
identity = profile.email or profile.account_identity or profile.profile_id
self.identity.configure(text=f"{identity}\n{profile.profile_id}")
families = (
", ".join(f"{family}: {state.status_label_ru}" for family, state in profile.model_states.items())
or "Семейства моделей: Н"
)
self.models.configure(text=families)
self.status.set_status(profile.health_state, profile.health_label_ru)
class HealthView(ctk.CTkFrame):
def __init__(
self, master: Any, app_state: Optional[Dict[str, Any]] = None, on_refresh: Optional[Callable] = None, **kwargs
):
super().__init__(master=master, fg_color="transparent", **kwargs)
self._rows: Dict[str, HealthProfileRow] = {}
SectionHeader(
self,
title="Состояние системы",
subtitle="Авторизация, локальное здоровье и наблюдаемые состояния моделей",
action_text="Обновить аудит",
action_cmd=on_refresh,
).pack(fill="x", padx=Theme.PAGE_PAD_X, pady=(Theme.PAGE_PAD_Y, Theme.SPACE_SM))
self.scroll = ctk.CTkScrollableFrame(self, fg_color="transparent")
self.scroll.pack(fill="both", expand=True, padx=Theme.PAGE_PAD_X, pady=(0, Theme.PAGE_PAD_Y))
self.banner = HubCard(self.scroll, border_color=Theme.BORDER_ACCENT, fg_color=Theme.DARK)
self.banner.pack(fill="x", pady=(0, Theme.SECTION_GAP))
self.title = ctk.CTkLabel(
self.banner, text="Ожидание snapshot", font=Theme.font_heading(), text_color=Theme.TEXT_ACCENT
)
self.title.pack(anchor="w", padx=Theme.CARD_PAD_X, pady=(Theme.CARD_PAD_Y, Theme.SPACE_XS))
self.summary = ctk.CTkLabel(self.banner, text="", font=Theme.font_body(), text_color=Theme.TEXT_SECONDARY)
self.summary.pack(anchor="w", padx=Theme.CARD_PAD_X, pady=(0, Theme.CARD_PAD_Y))
self.rows = ctk.CTkFrame(self.scroll, fg_color="transparent")
self.rows.pack(fill="x")
def update_data(self, snapshot: Optional[HubSnapshot] = None) -> None:
if not isinstance(snapshot, HubSnapshot):
return
readiness = snapshot.readiness
self.title.configure(text=readiness.title_ru)
warnings = "".join(readiness.warnings) if readiness.warnings else "Предупреждений нет"
self.summary.configure(
text=(
f"{readiness.summary_ru}\n"
f"Аккаунты {readiness.accounts_connected_count}/{readiness.total_accounts}"
f"Роли {readiness.roles_ready_count}/{readiness.total_roles}{warnings}"
)
)
live = set(snapshot.all_profiles)
for profile_id in list(self._rows):
if profile_id not in live:
self._rows.pop(profile_id).destroy()
ordered = sorted(snapshot.all_profiles.values(), key=lambda profile: (profile.provider, profile.display_name))
for index, profile in enumerate(ordered):
row = self._rows.get(profile.profile_id)
if row is None:
row = HealthProfileRow(self.rows)
self._rows[profile.profile_id] = row
row.update_profile(profile)
row.grid(row=index, column=0, sticky="ew", pady=Theme.SPACE_XS)
self.rows.grid_columnconfigure(0, weight=1)