From 5dd8fa1daa4da2e556e03b89d4f91cc015f99d6f Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Sun, 13 Sep 2026 19:26:25 +0530 Subject: [PATCH] fix(auxiliary): anthropic_messages profiles keep /reasoning reachable on aux calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commandcode-anthropic (api_mode=anthropic_messages, OpenAI-shaped base URL) lost thinking control on compression/title/vision calls after #109530: once its class overrides build_api_kwargs_extras, _project_provider_profile marks the profile as handling reasoning and drops the generic extra_body.reasoning fallback that the Anthropic adapter used to read — and the _reasoning_config gate only fired for provider=anthropic, Portal /v1/messages ids, /anthropic URLs and MiniMax. Carry the profile's api_mode on the projection and include it in that gate, so any anthropic_messages profile reaches the adapter regardless of URL shape. Chat-completions profiles are unchanged. Before: _build_call_kwargs("commandcode-anthropic", claude-haiku, {"enabled": False}) -> no _reasoning_config, no extra_body.reasoning; adapter defaults thinking. After: -> _reasoning_config={"enabled": False}. --- agent/auxiliary_client.py | 11 ++++++++--- tests/agent/test_auxiliary_client.py | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index ee9c556046..af95c63b0a 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -6052,6 +6052,7 @@ class _ProfileProjection(NamedTuple): reasoning_extra: Dict[str, Any] top_level: Dict[str, Any] handles_reasoning: bool + messages_wire: bool = False def _project_provider_profile( @@ -6062,11 +6063,13 @@ def _project_provider_profile( reasoning_extra: Dict[str, Any] = {} top_level: Dict[str, Any] = {} handles_reasoning = False + messages_wire = False try: from providers import get_provider_profile from providers.base import ProviderProfile profile = get_provider_profile(provider_norm) if profile is not None: + messages_wire = profile.api_mode == "anthropic_messages" body = profile.build_extra_body(model=model, base_url=effective_base, reasoning_config=reasoning_config) or {} reasoning_extra, top_level = profile.build_api_kwargs_extras( reasoning_config=reasoning_config, supports_reasoning=reasoning_config is not None, @@ -6082,7 +6085,7 @@ def _project_provider_profile( ) except Exception as exc: logger.debug("_build_call_kwargs: provider profile projection failed for %s: %s", provider, exc) - return _ProfileProjection(body, reasoning_extra, top_level, handles_reasoning) + return _ProfileProjection(body, reasoning_extra, top_level, handles_reasoning, messages_wire) def _merge_aux_extra_body( @@ -6148,11 +6151,13 @@ def _build_call_kwargs( kwargs["extra_body"] = merged_extra # Anthropic Messages adapters take reasoning via a private kwarg that plain OpenAI SDK clients # would reject; Portal Claude is dual-wire, so include it only when the catalog id selects - # /v1/messages. + # /v1/messages. A profile declaring api_mode=anthropic_messages (commandcode-anthropic) is on + # that wire regardless of URL shape — once it overrides build_api_kwargs_extras the generic + # ``extra_body.reasoning`` fallback the adapter used to read is gone, so this is its only path. if reasoning_config and isinstance(reasoning_config, dict): raw_base = base_url or "" if ( - provider_norm == "anthropic" or _nous_on_messages_wire(provider_norm, model) + provider_norm == "anthropic" or projection.messages_wire or _nous_on_messages_wire(provider_norm, model) or _endpoint_speaks_anthropic_messages(raw_base) or _is_anthropic_compat_endpoint(provider_norm, raw_base) ): kwargs["_reasoning_config"] = dict(reasoning_config) diff --git a/tests/agent/test_auxiliary_client.py b/tests/agent/test_auxiliary_client.py index ecd99c70a3..c59bb8aa1c 100644 --- a/tests/agent/test_auxiliary_client.py +++ b/tests/agent/test_auxiliary_client.py @@ -2946,6 +2946,26 @@ class TestAnthropicAuxiliaryReasoningTranslation: ) assert "_reasoning_config" not in openai_wire_kwargs + def test_anthropic_messages_profile_keeps_reasoning_reachable(self): + # commandcode-anthropic: OpenAI-shaped URL, anthropic_messages api_mode, and a profile + # class that overrides build_api_kwargs_extras (so the generic extra_body.reasoning + # fallback the adapter used to read is suppressed). The adapter must still be told. + import model_tools # noqa: F401 — triggers provider discovery + import providers + + assert providers.get_provider_profile("commandcode-anthropic") is not None + rc = {"enabled": False} + kwargs = _build_call_kwargs( + "commandcode-anthropic", "claude-haiku-4-5-20251001", [{"role": "user", "content": "hi"}], + reasoning_config=rc, base_url="https://api.commandcode.ai/provider/v1", + ) + assert kwargs["_reasoning_config"] == rc + chat_kwargs = _build_call_kwargs( + "commandcode", "Qwen/Qwen3.7-Max", [{"role": "user", "content": "hi"}], + reasoning_config=rc, base_url="https://api.commandcode.ai/provider/v1", + ) + assert "_reasoning_config" not in chat_kwargs + class TestAuxiliaryProviderProfileReasoning: """Auxiliary calls must reuse provider-profile reasoning wire shapes."""