Coverage for src/lilbee/runtime/progress/types.py: 100%
104 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
1"""Event type enums and Pydantic models for the progress protocol."""
3from enum import StrEnum
5from pydantic import BaseModel
8class EventType(StrEnum):
9 """Progress event types emitted during sync/ingest."""
11 FILE_START = "file_start"
12 FILE_DONE = "file_done"
13 BATCH_PROGRESS = "batch_progress"
14 DONE = "done"
15 EMBED = "embed"
16 EXTRACT = "extract"
17 CRAWL_START = "crawl_start"
18 CRAWL_PAGE = "crawl_page"
19 CRAWL_DONE = "crawl_done"
20 SETUP_START = "setup_start"
21 SETUP_PROGRESS = "setup_progress"
22 SETUP_DONE = "setup_done"
23 WIKI_PHASE = "wiki_phase"
24 WIKI_PAGE = "wiki_page"
27class SseEvent(StrEnum):
28 """SSE event names used in the HTTP streaming protocol."""
30 TOKEN = "token" # noqa: S105 -- SSE event name, not a credential
31 REASONING = "reasoning"
32 SOURCES = "sources"
33 ERROR = "error"
34 DONE = "done"
35 PROGRESS = "progress"
36 HEARTBEAT = "heartbeat"
37 ALREADY_INGESTING = "already_ingesting"
38 WARMING = "warming"
39 WARM = "warm"
40 COMPACTING = "compacting"
41 COMPACTION = "compaction"
42 MEMORY_EXTRACTED = "memory_extracted"
43 GPU_STATS = "gpu_stats"
46class SseErrorCode(StrEnum):
47 """Stable ``code`` values on SSE error events for clients to branch on."""
49 MODEL_TOO_LARGE = "model_too_large"
50 MODEL_NOT_INSTALLED = "model_not_installed"
51 INDEX_EMBEDDER_MISMATCH = "index_embedder_mismatch"
54class FileStartEvent(BaseModel):
55 """Emitted when a file begins ingestion."""
57 file: str
58 total_files: int
59 current_file: int
62class FileDoneEvent(BaseModel):
63 """Emitted when a file finishes ingestion (success or error)."""
65 file: str
66 status: str
67 chunks: int
70class BatchStatus(StrEnum):
71 """Status values for BatchProgressEvent.status."""
73 INGESTED = "ingested"
74 SKIPPED = "skipped"
75 FAILED = "failed"
76 RASTERIZING = "rasterizing"
79class BatchProgressEvent(BaseModel):
80 """Emitted after each file completes during batch ingestion."""
82 file: str
83 status: BatchStatus
84 current: int
85 total: int
88class ExtractEvent(BaseModel):
89 """Emitted with page-level extraction progress.
91 OCR fires one event per page as xberg processes it, as a running count
92 with ``total_pages == 0`` (the total is unknown mid-extraction). Extraction
93 then fires once per file with ``page == total_pages`` so subscribers see
94 "extracted N pages" before the embed phase ticks.
95 """
97 file: str
98 page: int
99 total_pages: int
102class EmbedEvent(BaseModel):
103 """Emitted per batch during embedding."""
105 file: str
106 chunk: int
107 total_chunks: int
110class CrawlStartEvent(BaseModel):
111 """Emitted when a crawl operation begins."""
113 url: str
114 depth: int
117# Sentinel used in CrawlPageEvent.total when the crawl's final page count is
118# not yet known (BFS streaming, page N emitted before N+1 is discovered).
119# Consumers (plugin, TUI, CLI) treat total <= 0 as indeterminate progress.
120CRAWL_TOTAL_UNKNOWN = -1
123class CrawlPageEvent(BaseModel):
124 """Emitted per page during crawling."""
126 url: str
127 current: int
128 total: int
131class CrawlDoneEvent(BaseModel):
132 """Emitted when a crawl operation completes."""
134 pages_crawled: int
135 files_written: int
138class SyncDoneEvent(BaseModel):
139 """Emitted when the sync operation completes."""
141 added: int
142 updated: int
143 removed: int
144 failed: int
145 skipped: int = 0
146 relocated: int = 0
149class SetupStartEvent(BaseModel):
150 """Emitted when a setup/bootstrap operation begins."""
152 component: str
153 size_estimate_bytes: int | None = None
156class SetupProgressEvent(BaseModel):
157 """Emitted periodically during a setup/bootstrap operation."""
159 component: str
160 downloaded_bytes: int
161 total_bytes: int | None = None
162 detail: str = ""
165class SetupDoneEvent(BaseModel):
166 """Emitted when a setup/bootstrap operation completes."""
168 component: str
169 success: bool
170 error: str | None = None
173class WikiPhase(StrEnum):
174 """Stage of a wiki build or synthesis run."""
176 EXTRACT = "extract"
177 GENERATE = "generate"
178 INDEX = "index"
181class WikiPhaseEvent(BaseModel):
182 """Emitted when a wiki run enters a new phase.
184 ``total`` is the number of units the phase will process (sources for a
185 build, clusters for synthesis), 0 where the phase has no unit count.
186 """
188 phase: WikiPhase
189 total: int = 0
192class WikiPageEvent(BaseModel):
193 """Emitted after each source (build) or cluster (synthesis) is written."""
195 label: str
196 pages: int
197 current: int
198 total: int