Coverage for src / lilbee / cli / tui / screens / model_info.py: 100%

47 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-05-15 20:55 +0000

1"""Modal showing the catalog row's HuggingFace metadata.""" 

2 

3from __future__ import annotations 

4 

5from typing import ClassVar 

6 

7from textual.app import ComposeResult 

8from textual.binding import Binding, BindingType 

9from textual.containers import Vertical, VerticalScroll 

10from textual.screen import ModalScreen 

11from textual.widgets import Markdown, Static 

12 

13from lilbee.cli.tui import messages as msg 

14from lilbee.cli.tui.screens.catalog_utils import LocalCatalogRow 

15 

16 

17class ModelInfoModal(ModalScreen[None]): 

18 """Read-only modal showing what we know about one catalog model.""" 

19 

20 CSS_PATH: ClassVar[str] = "model_info.tcss" 

21 

22 BINDINGS: ClassVar[list[BindingType]] = [ 

23 Binding("escape", "dismiss(None)", "Close", show=True), 

24 Binding("q", "dismiss(None)", "Close", show=False), 

25 Binding("i", "dismiss(None)", "Close", show=False), 

26 ] 

27 

28 def __init__(self, row: LocalCatalogRow) -> None: 

29 super().__init__() 

30 self._row = row 

31 

32 def compose(self) -> ComposeResult: 

33 with Vertical(id="info-root"): 

34 yield Static(self._row.name, id="info-title") 

35 yield Static(self._row.ref, id="info-ref") 

36 with VerticalScroll(id="info-body"): 

37 yield Markdown(self._build_markdown(), id="info-md") 

38 yield Static(msg.MODEL_INFO_HINT, id="info-hint") 

39 

40 def _build_markdown(self) -> str: 

41 row = self._row 

42 lines: list[str] = [] 

43 cm = row.catalog_model 

44 if cm is not None and cm.description: 

45 lines.append(cm.description) 

46 lines.append("") 

47 lines.append("**Task:** " + (row.task or "-")) 

48 if row.params: 

49 lines.append("**Parameters:** " + row.params) 

50 if row.size: 

51 lines.append("**Download size:** " + row.size) 

52 if cm is not None and cm.min_ram_gb: 

53 lines.append(f"**Recommended RAM:** {cm.min_ram_gb:g} GB") 

54 if row.quant: 

55 lines.append("**Quantization:** " + row.quant) 

56 if row.downloads: 

57 lines.append("**Downloads:** " + row.downloads) 

58 if row.installed: 

59 lines.append("**Status:** installed") 

60 if cm is not None and cm.gguf_filename and cm.gguf_filename != cm.hf_repo: 

61 lines.append("**GGUF file:** `" + cm.gguf_filename + "`") 

62 lines.append("") 

63 lines.append(msg.MODEL_INFO_HF_LINK.format(repo=row.ref)) 

64 return "\n".join(lines)