diff --git a/agent/model_metadata.py b/agent/model_metadata.py index 4493eae5f1f..01a96a735cd 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -700,7 +700,10 @@ def fetch_model_metadata(force_refresh: bool = False) -> Dict[str, Dict[str, Any return _model_metadata_cache try: - response = requests.get(OPENROUTER_MODELS_URL, timeout=10, verify=_resolve_requests_verify()) + # Tuple (connect, read) — flat timeout=10 means urllib3 can block 10s per + # retry stage through proxies that 403 CONNECT, ballooning to minutes + # (#46620). 5s connect / 10s read fails fast on unreachable hosts. + response = requests.get(OPENROUTER_MODELS_URL, timeout=(5, 10), verify=_resolve_requests_verify()) response.raise_for_status() data = response.json() @@ -778,7 +781,7 @@ def fetch_endpoint_model_metadata( response = requests.get( server_url.rstrip("/") + "/api/v1/models", headers=headers, - timeout=10, + timeout=(5, 10), verify=_resolve_requests_verify(), ) response.raise_for_status() @@ -826,7 +829,7 @@ def fetch_endpoint_model_metadata( for candidate in candidates: url = candidate.rstrip("/") + "/models" try: - response = requests.get(url, headers=headers, timeout=10, verify=_resolve_requests_verify()) + response = requests.get(url, headers=headers, timeout=(5, 10), verify=_resolve_requests_verify()) response.raise_for_status() payload = response.json() cache: Dict[str, Dict[str, Any]] = {} @@ -1406,7 +1409,7 @@ def _query_anthropic_context_length(model: str, base_url: str, api_key: str) -> "x-api-key": api_key, "anthropic-version": "2023-06-01", } - resp = requests.get(url, headers=headers, timeout=10, verify=_resolve_requests_verify()) + resp = requests.get(url, headers=headers, timeout=(5, 10), verify=_resolve_requests_verify()) if resp.status_code != 200: return None data = resp.json() @@ -1473,7 +1476,7 @@ def _fetch_codex_oauth_context_lengths(access_token: str) -> Dict[str, int]: resp = requests.get( "https://chatgpt.com/backend-api/codex/models?client_version=1.0.0", headers={"Authorization": f"Bearer {access_token}"}, - timeout=10, + timeout=(5, 10), verify=_resolve_requests_verify(), ) if resp.status_code != 200: diff --git a/model_tools.py b/model_tools.py index 0618138aa9a..5c1338f7fe1 100644 --- a/model_tools.py +++ b/model_tools.py @@ -552,7 +552,13 @@ def _resolve_active_context_length() -> int: if not model_id: return 0 from agent.model_metadata import get_model_context_length - return int(get_model_context_length(model_id) or 0) + # Honor explicit `model.context_length` in config.yaml — short-circuits + # the OpenRouter /models probe at get_model_context_length step 0, so + # non-OpenRouter providers don't pay the ~2-3s OpenRouter fetch at every + # CLI startup. See issue #46620. + raw_ctx = model_cfg.get("context_length") + config_ctx = raw_ctx if isinstance(raw_ctx, int) and raw_ctx > 0 else None + return int(get_model_context_length(model_id, config_context_length=config_ctx) or 0) except Exception as e: logger.debug("Could not resolve active context length: %s", e) return 0