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

1"""Event type enums and Pydantic models for the progress protocol.""" 

2 

3from enum import StrEnum 

4 

5from pydantic import BaseModel 

6 

7 

8class EventType(StrEnum): 

9 """Progress event types emitted during sync/ingest.""" 

10 

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 

24 

25class SseEvent(StrEnum): 

26 """SSE event names used in the HTTP streaming protocol.""" 

27 

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" 

37 

38 

39class SseErrorCode(StrEnum): 

40 """Stable ``code`` values on SSE error events for clients to branch on.""" 

41 

42 MODEL_TOO_LARGE = "model_too_large" 

43 MODEL_NOT_INSTALLED = "model_not_installed" 

44 INDEX_EMBEDDER_MISMATCH = "index_embedder_mismatch" 

45 

46 

47class FileStartEvent(BaseModel): 

48 """Emitted when a file begins ingestion.""" 

49 

50 file: str 

51 total_files: int 

52 current_file: int 

53 

54 

55class FileDoneEvent(BaseModel): 

56 """Emitted when a file finishes ingestion (success or error).""" 

57 

58 file: str 

59 status: str 

60 chunks: int 

61 

62 

63class BatchStatus(StrEnum): 

64 """Status values for BatchProgressEvent.status.""" 

65 

66 INGESTED = "ingested" 

67 SKIPPED = "skipped" 

68 FAILED = "failed" 

69 RASTERIZING = "rasterizing" 

70 

71 

72class BatchProgressEvent(BaseModel): 

73 """Emitted after each file completes during batch ingestion.""" 

74 

75 file: str 

76 status: BatchStatus 

77 current: int 

78 total: int 

79 

80 

81class ExtractEvent(BaseModel): 

82 """Emitted with page-level extraction progress. 

83 

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 """ 

89 

90 file: str 

91 page: int 

92 total_pages: int 

93 

94 

95class EmbedEvent(BaseModel): 

96 """Emitted per batch during embedding.""" 

97 

98 file: str 

99 chunk: int 

100 total_chunks: int 

101 

102 

103class CrawlStartEvent(BaseModel): 

104 """Emitted when a crawl operation begins.""" 

105 

106 url: str 

107 depth: int 

108 

109 

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 

114 

115 

116class CrawlPageEvent(BaseModel): 

117 """Emitted per page during crawling.""" 

118 

119 url: str 

120 current: int 

121 total: int 

122 

123 

124class CrawlDoneEvent(BaseModel): 

125 """Emitted when a crawl operation completes.""" 

126 

127 pages_crawled: int 

128 files_written: int 

129 

130 

131class SyncDoneEvent(BaseModel): 

132 """Emitted when the sync operation completes.""" 

133 

134 added: int 

135 updated: int 

136 removed: int 

137 failed: int 

138 skipped: int = 0 

139 

140 

141class SetupStartEvent(BaseModel): 

142 """Emitted when a setup/bootstrap operation begins.""" 

143 

144 component: str 

145 size_estimate_bytes: int | None = None 

146 

147 

148class SetupProgressEvent(BaseModel): 

149 """Emitted periodically during a setup/bootstrap operation.""" 

150 

151 component: str 

152 downloaded_bytes: int 

153 total_bytes: int | None = None 

154 detail: str = "" 

155 

156 

157class SetupDoneEvent(BaseModel): 

158 """Emitted when a setup/bootstrap operation completes.""" 

159 

160 component: str 

161 success: bool 

162 error: str | None = None