Coverage for src / lilbee / catalog / models.py: 100%
59 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-06-28 01:01 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-06-28 01:01 +0000
1"""Catalog dataclasses and pydantic types: leaf module, no sibling imports."""
3from dataclasses import dataclass
5from pydantic import BaseModel
7from lilbee.catalog.types import ModelCompat, ModelTask
10class HfGgufMeta(BaseModel):
11 """GGUF metadata returned by the HF API when expand=gguf is requested.
13 ModelInfo.gguf is typed as ``dict | None`` upstream, so we validate it ourselves.
14 """
16 total: int = 0
17 architecture: str = ""
18 context_length: int = 0
21@dataclass
22class DownloadProgress:
23 """Human-readable snapshot of download progress.
25 ``percent`` is a float (0.0 to 100.0) so the ProgressBar renders smooth
26 fractional movement during multi-GB downloads. Call sites that need
27 an integer for display format it themselves.
28 """
30 percent: float
31 detail: str
32 is_cache_hit: bool
35@dataclass(frozen=True)
36class CatalogModel:
37 """One catalog entry, keyed by HuggingFace repo. ``gguf_filename`` may be a glob."""
39 hf_repo: str
40 gguf_filename: str
41 size_gb: float
42 min_ram_gb: float
43 description: str
44 featured: bool
45 downloads: int
46 task: ModelTask
47 recommended: bool = False
48 architecture: str = ""
49 compat: ModelCompat = ModelCompat.UNKNOWN
51 @property
52 def ref(self) -> str:
53 """Browse-time ref (the HF repo); concrete filename is resolved at install."""
54 return self.hf_repo
56 @property
57 def display_name(self) -> str:
58 """Human-readable label derived from the HuggingFace repo id."""
59 # Local import keeps models.py a leaf (no sibling imports at module top).
60 from lilbee.catalog.formatting import clean_display_name
62 return clean_display_name(self.hf_repo)
65@dataclass(frozen=True)
66class CatalogResult:
67 """Paginated catalog result."""
69 total: int
70 limit: int
71 offset: int
72 models: list[CatalogModel]
73 has_more: bool = False
76@dataclass(frozen=True)
77class HfPage:
78 """One page of HuggingFace API results."""
80 models: list[CatalogModel]
81 has_more: bool
84@dataclass(frozen=True)
85class ModelVariant:
86 """One quantization within a model family. ``filename`` may be a glob."""
88 hf_repo: str
89 filename: str
90 param_count: str
91 quant: str
92 size_mb: int
93 recommended: bool
94 mmproj_filename: str = ""
97@dataclass(frozen=True)
98class ModelFamily:
99 """A group of related model variants (e.g. Qwen3 in multiple sizes)."""
101 slug: str # family slug for building refs: "qwen3"
102 name: str # display name: "Qwen3"
103 task: ModelTask
104 description: str
105 variants: tuple[ModelVariant, ...]