feat: sleep duration timer in stats panel

Track sleeping_since (ISO timestamp) in ServerState; auto-cleared by _set()
whenever state leaves sleeping. Frontend runs a 1s interval showing elapsed
time as "Xs", "Xm Ys", or "Xh Ym" in a new ASLEEP stat row (visible only
during state-sleeping). Timer survives page reload via server-side timestamp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad Doloman
2026-06-28 13:49:50 +03:00
parent a5e59df624
commit 71b3c945ee
4 changed files with 59 additions and 4 deletions

View File

@@ -51,6 +51,7 @@ class ServerState:
loading: Optional[LoadingInfo] = None
metrics: Metrics = field(default_factory=Metrics)
request_count: int = 0
sleeping_since: Optional[str] = None # ISO timestamp when sleeping started
def to_dict(self) -> dict:
return {
@@ -59,6 +60,7 @@ class ServerState:
"loading": asdict(self.loading) if self.loading else None,
"metrics": asdict(self.metrics),
"request_count": self.request_count,
"sleeping_since": self.sleeping_since,
"timestamp": datetime.now().isoformat(timespec="seconds"),
}
@@ -215,12 +217,17 @@ class LogParser:
self._state.model = model_id
return self._set(state="idle", loading=None)
if s == "sleeping":
return self._set(state="sleeping")
return self._set(
state="sleeping",
sleeping_since=datetime.now().isoformat(timespec="seconds"),
)
return None
# ── Helpers ──────────────────────────────────────────────────────────────
def _set(self, **kwargs) -> ServerState:
if "state" in kwargs and kwargs["state"] != "sleeping":
self._state.sleeping_since = None
for k, v in kwargs.items():
setattr(self._state, k, v)
return self._state