From ffc6dc020750a67b9c0889dd41979a0e5f63ea16 Mon Sep 17 00:00:00 2001 From: safishamsi Date: Wed, 29 Jul 2026 17:25:08 +0100 Subject: [PATCH] fix(llm): correct bedrock max_attempts semantics + stub botocore.config in the reasoning test (follow-up to #2283/#2288) botocore max_attempts counts the initial call, so GRAPHIFY_MAX_RETRIES must map to _resolve_max_retries() + 1 (a value of 6 -> 7 total attempts; 0 -> 1, i.e. no retry). Also stub botocore.config in the #2288 reasoning-model test, which broke once #2283 added the botocore.config import. Co-Authored-By: Claude Opus 4.8 (1M context) --- graphify/llm.py | 4 ++-- tests/test_image_vision.py | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/graphify/llm.py b/graphify/llm.py index ac8b6b20..30d7a6d6 100644 --- a/graphify/llm.py +++ b/graphify/llm.py @@ -1653,7 +1653,7 @@ def _call_bedrock(model: str, user_message: str, max_tokens: int = 8192, *, deep config=botocore.config.Config( read_timeout=_resolve_api_timeout(), connect_timeout=10, - retries={"max_attempts": _resolve_max_retries(), "mode": "adaptive"}, + retries={"max_attempts": _resolve_max_retries() + 1, "mode": "adaptive"}, ), ) @@ -2613,7 +2613,7 @@ def _call_llm( config=botocore.config.Config( read_timeout=_resolve_api_timeout(), connect_timeout=10, - retries={"max_attempts": _resolve_max_retries(), "mode": "adaptive"}, + retries={"max_attempts": _resolve_max_retries() + 1, "mode": "adaptive"}, ), ) resp = client.converse( diff --git a/tests/test_image_vision.py b/tests/test_image_vision.py index 39910d91..e50d0bc4 100644 --- a/tests/test_image_vision.py +++ b/tests/test_image_vision.py @@ -420,9 +420,13 @@ def test_call_bedrock_parses_reasoning_model_response(monkeypatch): botocore = types.ModuleType("botocore") exc = types.ModuleType("botocore.exceptions") exc.ClientError = type("ClientError", (Exception,), {}) + config_mod = types.ModuleType("botocore.config") + config_mod.Config = lambda **kw: SimpleNamespace(**kw) botocore.exceptions = exc + botocore.config = config_mod monkeypatch.setitem(sys.modules, "botocore", botocore) monkeypatch.setitem(sys.modules, "botocore.exceptions", exc) + monkeypatch.setitem(sys.modules, "botocore.config", config_mod) _fake(monkeypatch) result = llm._call_bedrock("model", "CORPUS") @@ -442,7 +446,7 @@ def test_call_bedrock_honors_api_timeout(monkeypatch): assert cfg is not None, "bedrock client built without a botocore config" assert cfg.read_timeout == 1800.0 assert cfg.connect_timeout == 10 - assert cfg.retries == {"max_attempts": 6, "mode": "adaptive"} + assert cfg.retries == {"max_attempts": 7, "mode": "adaptive"} # retries + initial attempt def test_call_bedrock_api_timeout_defaults_when_unset(monkeypatch):