diff --git a/EvoScientist/cli/__init__.py b/EvoScientist/cli/__init__.py index 5fe976f..530c2a9 100644 --- a/EvoScientist/cli/__init__.py +++ b/EvoScientist/cli/__init__.py @@ -79,6 +79,11 @@ def main(): warnings.filterwarnings( "ignore", message=".*type is unknown and inference may fail.*" ) + # v3 streaming is a deliberate choice (#268), so its beta notice is noise. + # Matched by message, not category, to keep other beta warnings visible. + warnings.filterwarnings( + "ignore", message=".*v3 streaming protocol on Pregel is experimental.*" + ) from ..config import load_config from .commands import _configure_logging diff --git a/pyproject.toml b/pyproject.toml index de7c188..6b0300a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,8 @@ dependencies = [ "langchain-google-genai>=4.2", "langchain-ollama>=1.1", "langchain-openrouter>=0.2.5", + # 0.11.0+ SSE regressions: teardown noise + mid-turn ReadTimeout + "openrouter>=0.10.8,<0.11.0", "tavily-python>=0.7", "pyyaml>=6.0", "rich>=15.0", diff --git a/tests/test_llm.py b/tests/test_llm.py index f5f25d4..33c0fef 100644 --- a/tests/test_llm.py +++ b/tests/test_llm.py @@ -381,6 +381,13 @@ class TestSlashModelIdFallback: # ============================================================================= +def _sdk_retry_supports_status_codes_override() -> bool: + """openrouter>=0.11 only; the 429 override degrades to a no-op below that.""" + from openrouter.utils.retries import RetryConfig + + return "status_codes_override" in getattr(RetryConfig, "__annotations__", {}) + + class TestThirdPartyRouting: @patch("EvoScientist.llm.models.init_chat_model") def test_siliconflow_routes_through_openai(self, mock_init, monkeypatch): @@ -471,6 +478,11 @@ class TestThirdPartyRouting: # --- OpenRouter upstream 429 retry --- + @pytest.mark.skipif( + not _sdk_retry_supports_status_codes_override(), + reason="openrouter<0.11 RetryConfig lacks status_codes_override; " + "the 429 override no-ops there by design (models.py hasattr guard)", + ) def test_openrouter_429_added_to_retryable_status_codes(self, monkeypatch): """Upstream 429s must become retryable on the real SDK client. @@ -501,6 +513,11 @@ class TestThirdPartyRouting: retry_config = model.client.sdk_configuration.retry_config assert getattr(retry_config, "status_codes_override", None) is None + @pytest.mark.skipif( + not _sdk_retry_supports_status_codes_override(), + reason="openrouter<0.11 RetryConfig lacks status_codes_override; " + "the 429 override no-ops there by design (models.py hasattr guard)", + ) def test_openrouter_429_retried_on_the_wire(self, monkeypatch): """End-to-end: a 429 with Retry-After is retried and the retry succeeds.""" import httpx diff --git a/uv.lock b/uv.lock index 5893703..5e9b492 100644 --- a/uv.lock +++ b/uv.lock @@ -973,6 +973,7 @@ dependencies = [ { name = "lazy-loader" }, { name = "markdownify" }, { name = "nest-asyncio" }, + { name = "openrouter" }, { name = "prompt-toolkit" }, { name = "psutil" }, { name = "python-dotenv" }, @@ -1083,6 +1084,7 @@ requires-dist = [ { name = "lazy-loader", specifier = ">=0.5" }, { name = "markdownify", specifier = ">=1.2" }, { name = "nest-asyncio", specifier = ">=1.6" }, + { name = "openrouter", specifier = ">=0.10.8,<0.11.0" }, { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.5.0" }, { name = "prompt-toolkit", specifier = ">=3.0" }, { name = "psutil", specifier = ">=6.0" }, @@ -2920,7 +2922,7 @@ wheels = [ [[package]] name = "openrouter" -version = "0.11.44" +version = "0.10.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpcore" }, @@ -2928,9 +2930,9 @@ dependencies = [ { name = "jsonpath-python" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/66/1c239f07abd22c7eb505e664deb31eee7b9d1451a4f7e7249e60711b42b7/openrouter-0.11.44.tar.gz", hash = "sha256:7a61c42949a96a6c2da2bb7810f7ba99581271c2344deecff34d2bbae9b83157", size = 380246, upload-time = "2026-07-17T20:59:07.669Z" } +sdist = { url = "https://files.pythonhosted.org/packages/38/4c/1fed3f4cbcf0962d8117b54f1740696c98d0dc2e3d5c34459d46effe8a3b/openrouter-0.10.8.tar.gz", hash = "sha256:ac7f4cea1ec1c2a063b0ad9792a8f64dde68ed053279b6c42bee849a50afc47c", size = 340259, upload-time = "2026-06-28T15:33:38.067Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/c4/1572fff0d9169c0aa849ebaa7d492508eb2d4d583b8b5caf9a5a97760123/openrouter-0.11.44-py3-none-any.whl", hash = "sha256:b787f132a00fe058d8772985d5ec25dfa446b2ad00309be03143f8d8f5b5371b", size = 837128, upload-time = "2026-07-17T20:59:06.287Z" }, + { url = "https://files.pythonhosted.org/packages/15/ae/76fc8ad57f6717e9231fbd7313e5623733d86f1a2149baa458772164f456/openrouter-0.10.8-py3-none-any.whl", hash = "sha256:ff9b3cd2f55a3f905d21f56517344da9f9556ffbd2cb9d31ddc388c4b930aab6", size = 748497, upload-time = "2026-06-28T15:33:36.627Z" }, ] [[package]]