diff --git a/agent/model_metadata.py b/agent/model_metadata.py index bd974af5e8..41c8fe6796 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -1452,6 +1452,15 @@ def save_context_length(model: str, base_url: str, length: int) -> None: Cache key is ``model@base_url`` so the same model name served from different providers can have different limits. """ + # Never persist non-positive values — a 0 or negative context length + # is always a bug and would poison the cache, causing downstream + # `get_model_context_length()` to return 0 (since `0 is not None`). + if length <= 0: + logger.warning( + "Refusing to cache non-positive context length %s -> %s tokens", + f"{model}@{base_url}", length, + ) + return key = _context_cache_key(model, base_url) cache = _load_context_cache() if cache.get(key) == length: @@ -2664,8 +2673,19 @@ def get_model_context_length( if base_url and not _skip_persistent_context_cache(base_url, provider): cached = get_cached_context_length(model, base_url) if cached is not None: + # Reject non-positive cached values — a 0 or negative value + # is always a bug (corrupted cache, probe failure, or manual + # edit). Without this guard, `0 is not None` short-circuits + # the resolution chain and the compressor gets context_length=0, + # breaking every status-bar and /usage display downstream. + if cached <= 0: + logger.warning( + "Dropping non-positive cache entry %s@%s -> %s; re-resolving", + model, base_url, cached, + ) + _invalidate_cached_context_length(model, base_url) # Invalidate stale 32k cache entries for Kimi-family models. - if cached <= 32768 and _model_name_suggests_kimi(model): + elif cached <= 32768 and _model_name_suggests_kimi(model): logger.info( "Dropping stale Kimi cache entry %s@%s -> %s (OpenRouter underreport); " "re-resolving via hardcoded defaults",