Complete state of an active streaming operation. This replaces scattered state variables with a single, type-safe model.
| 135 | |
| 136 | |
| 137 | class StreamingState(BaseModel): |
| 138 | """Complete state of an active streaming operation. |
| 139 | |
| 140 | This replaces scattered state variables with a single, type-safe model. |
| 141 | """ |
| 142 | |
| 143 | # Content accumulation |
| 144 | accumulated_content: str = Field( |
| 145 | default="", description="All content received so far" |
| 146 | ) |
| 147 | reasoning_content: str = Field( |
| 148 | default="", description="Reasoning/thinking content accumulated" |
| 149 | ) |
| 150 | |
| 151 | # Chunk tracking |
| 152 | chunks_received: int = Field(default=0, description="Total chunks processed") |
| 153 | last_chunk_time: float = Field( |
| 154 | default_factory=time.time, description="Timestamp of last chunk" |
| 155 | ) |
| 156 | |
| 157 | # Content detection |
| 158 | detected_type: ContentType = Field( |
| 159 | default=ContentType.UNKNOWN, description="Detected content type" |
| 160 | ) |
| 161 | |
| 162 | # Phase tracking |
| 163 | phase: StreamingPhase = Field( |
| 164 | default=StreamingPhase.INITIALIZING, description="Current streaming phase" |
| 165 | ) |
| 166 | |
| 167 | # Timing |
| 168 | start_time: float = Field( |
| 169 | default_factory=time.time, description="When streaming started" |
| 170 | ) |
| 171 | end_time: float | None = Field(default=None, description="When streaming completed") |
| 172 | |
| 173 | # Completion |
| 174 | finish_reason: str | None = Field(default=None, description="Why streaming ended") |
| 175 | interrupted: bool = Field(default=False, description="Whether user interrupted") |
| 176 | |
| 177 | # Buffer caps |
| 178 | max_accumulated_chars: int = Field( |
| 179 | default=1_048_576, |
| 180 | description="Max accumulated content chars (0=unlimited)", |
| 181 | ) |
| 182 | max_chunks: int = Field( |
| 183 | default=50_000, |
| 184 | description="Max chunks before stall detection (0=unlimited)", |
| 185 | ) |
| 186 | content_capped: bool = Field( |
| 187 | default=False, description="Whether content hit the buffer cap" |
| 188 | ) |
| 189 | |
| 190 | model_config = {"frozen": False} |
| 191 | |
| 192 | @property |
| 193 | def elapsed_time(self) -> float: |
| 194 | """Calculate elapsed time since streaming started.""" |
no outgoing calls