diff --git a/run_agent.py b/run_agent.py index 625dc5fce2..54f18d1a1d 100644 --- a/run_agent.py +++ b/run_agent.py @@ -6688,6 +6688,18 @@ class AIAgent: options["num_ctx"] = self._ollama_num_ctx extra_body["options"] = options + # Ollama / custom provider: pass think=false when reasoning is disabled. + # Ollama does not recognise the OpenRouter-style `reasoning` extra_body + # field, so we use its native `think` parameter instead. + # This prevents thinking-capable models (Qwen3, etc.) from generating + # blocks and producing empty-response errors when the user has + # set reasoning_effort: none. + if self.provider == "custom" and self.reasoning_config and isinstance(self.reasoning_config, dict): + _effort = (self.reasoning_config.get("effort") or "").strip().lower() + _enabled = self.reasoning_config.get("enabled", True) + if _effort == "none" or _enabled is False: + extra_body["think"] = False + if self._is_qwen_portal(): extra_body["vl_high_resolution_images"] = True diff --git a/tests/run_agent/test_run_agent.py b/tests/run_agent/test_run_agent.py index 7422f22f1f..ee67f15b05 100644 --- a/tests/run_agent/test_run_agent.py +++ b/tests/run_agent/test_run_agent.py @@ -928,6 +928,7 @@ class TestBuildApiKwargs: kwargs = agent._build_api_kwargs(messages) assert kwargs["max_tokens"] == 4096 + def test_qwen_portal_formats_messages_and_metadata(self, agent): agent.base_url = "https://portal.qwen.ai/v1" agent._base_url_lower = agent.base_url.lower() @@ -983,6 +984,46 @@ class TestBuildApiKwargs: messages = [{"role": "system", "content": "sys"}, {"role": "user", "content": "hi"}] kwargs = agent._build_api_kwargs(messages) assert kwargs["max_tokens"] == 65536 +======= + def test_ollama_think_false_on_effort_none(self, agent): + """Custom (Ollama) provider with effort=none should inject think=false.""" + agent.provider = "custom" + agent.base_url = "http://localhost:11434/v1" + agent._base_url_lower = agent.base_url.lower() + agent.reasoning_config = {"effort": "none"} + messages = [{"role": "user", "content": "hi"}] + kwargs = agent._build_api_kwargs(messages) + assert kwargs.get("extra_body", {}).get("think") is False + + def test_ollama_think_false_on_enabled_false(self, agent): + """Custom (Ollama) provider with enabled=false should inject think=false.""" + agent.provider = "custom" + agent.base_url = "http://localhost:11434/v1" + agent._base_url_lower = agent.base_url.lower() + agent.reasoning_config = {"enabled": False} + messages = [{"role": "user", "content": "hi"}] + kwargs = agent._build_api_kwargs(messages) + assert kwargs.get("extra_body", {}).get("think") is False + + def test_ollama_no_think_param_when_reasoning_enabled(self, agent): + """Custom provider with reasoning enabled should NOT inject think=false.""" + agent.provider = "custom" + agent.base_url = "http://localhost:11434/v1" + agent._base_url_lower = agent.base_url.lower() + agent.reasoning_config = {"enabled": True, "effort": "medium"} + messages = [{"role": "user", "content": "hi"}] + kwargs = agent._build_api_kwargs(messages) + assert kwargs.get("extra_body", {}).get("think") is None + + def test_non_custom_provider_unaffected(self, agent): + """OpenRouter provider with effort=none should NOT inject think=false.""" + agent.provider = "openrouter" + agent.model = "qwen/qwen3.5-plus-02-15" + agent.reasoning_config = {"effort": "none"} + messages = [{"role": "user", "content": "hi"}] + kwargs = agent._build_api_kwargs(messages) + assert kwargs.get("extra_body", {}).get("think") is None + class TestBuildAssistantMessage: