fix: refresh optional CLI Apps catalogs

maintainer edit: CLI Apps settings now treats optional catalog caches as refresh candidates without blocking the initial payload, and pending polling stops when refresh is throttled instead of running indefinitely.
This commit is contained in:
chengyongru
2026-06-22 17:14:13 +08:00
committed by Xubin Ren
parent 2216405821
commit dd2cb4ca91
5 changed files with 95 additions and 13 deletions
+65 -5
View File
@@ -6,10 +6,18 @@ from nanobot.webui import cli_apps_api
class _FakeManager:
def __init__(self, *, fresh: bool, apps: list[dict[str, Any]] | None = None) -> None:
def __init__(
self,
*,
fresh: bool,
apps: list[dict[str, Any]] | None = None,
all_sources_fresh: bool | None = None,
) -> None:
self.fresh = fresh
self.all_sources_fresh = fresh if all_sources_fresh is None else all_sources_fresh
self.apps = apps or []
self.payload_calls: list[bool] = []
self.fresh_checks: list[bool] = []
def payload(self, *, cache_only: bool = False) -> dict[str, Any]:
self.payload_calls.append(cache_only)
@@ -19,8 +27,9 @@ class _FakeManager:
"catalog_updated_at": "2026-04-18" if self.apps else None,
}
def catalog_cache_fresh(self) -> bool:
return self.fresh
def catalog_cache_fresh(self, *, include_optional: bool = False) -> bool:
self.fresh_checks.append(include_optional)
return self.all_sources_fresh if include_optional else self.fresh
def installed_payload(self) -> dict[str, Any]:
return {
@@ -51,11 +60,12 @@ def test_cli_apps_payload_uses_cache_and_marks_refresh_pending(monkeypatch) -> N
manager = _FakeManager(fresh=False)
refreshes = []
monkeypatch.setattr(cli_apps_api, "_manager", lambda: manager)
monkeypatch.setattr(cli_apps_api, "_start_catalog_refresh", lambda: refreshes.append(True))
monkeypatch.setattr(cli_apps_api, "_start_catalog_refresh", lambda: refreshes.append(True) or True)
payload = cli_apps_api.cli_apps_payload()
assert manager.payload_calls == [True]
assert manager.fresh_checks == [True]
assert refreshes == [True]
assert payload["catalog_refresh_pending"] is True
assert payload["apps"][0]["name"] == "gimp"
@@ -85,11 +95,61 @@ def test_cli_apps_payload_skips_refresh_when_cache_is_fresh(monkeypatch) -> None
)
refreshes = []
monkeypatch.setattr(cli_apps_api, "_manager", lambda: manager)
monkeypatch.setattr(cli_apps_api, "_start_catalog_refresh", lambda: refreshes.append(True))
monkeypatch.setattr(cli_apps_api, "_start_catalog_refresh", lambda: refreshes.append(True) or True)
payload = cli_apps_api.cli_apps_payload()
assert manager.payload_calls == [True]
assert manager.fresh_checks == [True]
assert refreshes == []
assert payload["catalog_refresh_pending"] is False
assert payload["apps"][0]["source"] == "harness"
def test_cli_apps_payload_refreshes_when_optional_cache_is_stale(monkeypatch) -> None:
manager = _FakeManager(
fresh=True,
all_sources_fresh=False,
apps=[
{
"name": "gimp",
"display_name": "GIMP",
"category": "image",
"description": "Image editing",
"requires": "Python",
"source": "harness",
"entry_point": "cli-anything-gimp",
"install_supported": True,
"installed": False,
"available": False,
"status": "not_installed",
"logo_url": None,
"brand_color": None,
"skill_installed": False,
}
],
)
refreshes = []
monkeypatch.setattr(cli_apps_api, "_manager", lambda: manager)
monkeypatch.setattr(cli_apps_api, "_start_catalog_refresh", lambda: refreshes.append(True) or True)
payload = cli_apps_api.cli_apps_payload()
assert manager.payload_calls == [True]
assert manager.fresh_checks == [True]
assert refreshes == [True]
assert payload["catalog_refresh_pending"] is True
assert payload["apps"][0]["source"] == "harness"
def test_cli_apps_payload_reports_not_pending_when_refresh_is_throttled(monkeypatch) -> None:
manager = _FakeManager(fresh=False)
monkeypatch.setattr(cli_apps_api, "_manager", lambda: manager)
monkeypatch.setattr(cli_apps_api, "_start_catalog_refresh", lambda: False)
payload = cli_apps_api.cli_apps_payload()
assert manager.payload_calls == [True]
assert manager.fresh_checks == [True]
assert payload["catalog_refresh_pending"] is False
assert payload["apps"][0]["name"] == "gimp"