"""Layer-neutral schema for operator-visible progress updates."""from__future__importannotationsfrompydanticimportBaseModel,Fieldfrom.modelsimportSTRICT_FROZEN_CONFIG
[docs]classOperatorProgress(BaseModel):"""Actionable progress text plus an optional live countdown duration."""model_config=STRICT_FROZEN_CONFIGmessage:str=Field(min_length=1)timeout_seconds:int|None=Field(default=None,gt=0)
[docs]defrender(self,*,remaining_seconds:int|None=None)->str:"""Render the update for a frontend that cannot animate a timer."""seconds=self.timeout_secondsifremaining_secondsisNoneelseremaining_secondsifsecondsisNone:returnself.messageminutes,remainder=divmod(max(0,seconds),60)returnf"{self.message} Time remaining {minutes}:{remainder:02d}."