Coverage for src / lilbee / runtime / progress / types.py: 100%
84 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"""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"
25class SseEvent(StrEnum):
26 """SSE event names used in the HTTP streaming protocol."""
28 TOKEN = "token" # noqa: S105 -- SSE event name, not a credential
29 REASONING = "reasoning"
30 SOURCES = "sources"
31 ERROR = "error"
32 DONE = "done"
33 PROGRESS = "progress"
34 HEARTBEAT = "heartbeat"
35 ALREADY_INGESTING = "already_ingesting"
36 MEMORY_EXTRACTED = "memory_extracted"
39class SseErrorCode(StrEnum):
40 """Stable ``code`` values on SSE error events for clients to branch on."""
42 MODEL_TOO_LARGE = "model_too_large"
43 MODEL_NOT_INSTALLED = "model_not_installed"
44 INDEX_EMBEDDER_MISMATCH = "index_embedder_mismatch"
47class FileStartEvent(BaseModel):
48 """Emitted when a file begins ingestion."""
50 file: str
51 total_files: int
52 current_file: int
55class FileDoneEvent(BaseModel):
56 """Emitted when a file finishes ingestion (success or error)."""
58 file: str
59 status: str
60 chunks: int
63class BatchStatus(StrEnum):
64 """Status values for BatchProgressEvent.status."""
66 INGESTED = "ingested"
67 SKIPPED = "skipped"
68 FAILED = "failed"
69 RASTERIZING = "rasterizing"
72class BatchProgressEvent(BaseModel):
73 """Emitted after each file completes during batch ingestion."""
75 file: str
76 status: BatchStatus
77 current: int
78 total: int
81class ExtractEvent(BaseModel):
82 """Emitted with page-level extraction progress.
84 Vision PDF OCR fires one event per page (``page < total_pages``);
85 plain (non-OCR) extraction fires once per file with
86 ``page == total_pages`` so subscribers see "extracted N pages"
87 before the embed phase ticks.
88 """
90 file: str
91 page: int
92 total_pages: int
95class EmbedEvent(BaseModel):
96 """Emitted per batch during embedding."""
98 file: str
99 chunk: int
100 total_chunks: int
103class CrawlStartEvent(BaseModel):
104 """Emitted when a crawl operation begins."""
106 url: str
107 depth: int
110# Sentinel used in CrawlPageEvent.total when the crawl's final page count is
111# not yet known (BFS streaming, page N emitted before N+1 is discovered).
112# Consumers (plugin, TUI, CLI) treat total <= 0 as indeterminate progress.
113CRAWL_TOTAL_UNKNOWN = -1
116class CrawlPageEvent(BaseModel):
117 """Emitted per page during crawling."""
119 url: str
120 current: int
121 total: int
124class CrawlDoneEvent(BaseModel):
125 """Emitted when a crawl operation completes."""
127 pages_crawled: int
128 files_written: int
131class SyncDoneEvent(BaseModel):
132 """Emitted when the sync operation completes."""
134 added: int
135 updated: int
136 removed: int
137 failed: int
138 skipped: int = 0
141class SetupStartEvent(BaseModel):
142 """Emitted when a setup/bootstrap operation begins."""
144 component: str
145 size_estimate_bytes: int | None = None
148class SetupProgressEvent(BaseModel):
149 """Emitted periodically during a setup/bootstrap operation."""
151 component: str
152 downloaded_bytes: int
153 total_bytes: int | None = None
154 detail: str = ""
157class SetupDoneEvent(BaseModel):
158 """Emitted when a setup/bootstrap operation completes."""
160 component: str
161 success: bool
162 error: str | None = None