nanobot/nanobot/webui/version_check.py
Jiajun Xie 4255656089 refactor(webui): replace real-time polling with click-to-check version updates
- Remove background PyPI polling loop and WebSocket broadcast
- Remove UpdateBanner from ThreadHeader (keep main page clean)
- Add on-demand version check endpoint (GET /api/settings/version-check)
- Add 'About' section in Settings > Overview with check-for-updates button
- Design: no auto-fetch, user initiates check explicitly via button click
2026-06-10 18:11:06 +08:00

52 lines
1.5 KiB
Python

"""On-demand version checker for nanobot-ai releases.
Checks PyPI for newer versions when explicitly requested (no background polling).
"""
from __future__ import annotations
import logging
import time
from typing import Any
import httpx
from nanobot import __version__
logger = logging.getLogger(__name__)
_PYPI_URL = "https://pypi.org/pypi/nanobot-ai/json"
_CACHE_TTL_S = 300 # 5 minutes cache to avoid hammering PyPI
_cache: tuple[float, str | None] = (0.0, None)
def check_for_update() -> dict[str, Any] | None:
"""Check PyPI for a newer version. Returns update info dict or None if up-to-date.
Uses a short cache to avoid repeated requests within the TTL window.
This is a blocking call — invoke from a thread or background task.
"""
global _cache
now = time.monotonic()
cached_at, cached_val = _cache
if now - cached_at < _CACHE_TTL_S and cached_val is not None:
latest = cached_val
else:
try:
resp = httpx.get(_PYPI_URL, timeout=5.0, follow_redirects=True)
resp.raise_for_status()
latest = resp.json().get("info", {}).get("version")
except Exception:
logger.debug("PyPI version check failed", exc_info=True)
return None
_cache = (now, latest)
if not latest or latest == __version__:
return None
return {
"currentVersion": __version__,
"latestVersion": latest,
"pypiUrl": "https://pypi.org/project/nanobot-ai/",
}