"""An open AITURK picker discovers changes without an explicit refresh.""" import threading import time from hermes_cli import models def test_cache_only_picker_refreshes_stale_aiturk_catalog(tmp_path, monkeypatch): monkeypatch.setenv("HERMES_HOME", str(tmp_path)) url = "https://ai.turkservis.online/v1" key = "test-only" fp = models._custom_endpoint_fingerprint(key, None, None) models._save_provider_models_cache({"custom:" + url: { "fp": fp, "at": time.time() - 90, "models": ["old"]}}) started = threading.Event() release = threading.Event() def fetch(*args, **kwargs): started.set() assert release.wait(5) return ["new-model", "new-combo"] monkeypatch.setattr(models, "fetch_api_models", fetch) try: assert models.cached_fetch_api_models(key, url, cache_only=True) == ["old"] assert started.wait(5) finally: release.set() deadline = time.monotonic() + 5 while time.monotonic() < deadline: result = models.cached_fetch_api_models(key, url, cache_only=True) if result == ["new-model", "new-combo"]: break time.sleep(0.02) assert result == ["new-model", "new-combo"] def test_background_refresh_preserves_context_scope(tmp_path, monkeypatch): import contextvars scope = contextvars.ContextVar("test_catalog_scope", default="wrong") seen = [] done = threading.Event() monkeypatch.setattr(models, "_provider_models_cache_path", lambda: tmp_path / scope.get()) monkeypatch.setattr(models, "_load_provider_models_cache", lambda: {}) def save(cache): seen.append((scope.get(), cache)) done.set() monkeypatch.setattr(models, "_save_provider_models_cache", save) token = scope.set("selected-profile") try: models._spawn_swr_refresh("scope-test", lambda: {"models": [scope.get()]}) finally: scope.reset(token) assert done.wait(5) assert seen == [("selected-profile", {"scope-test": {"models": ["selected-profile"]}})]