Commit 4e5116f47 for llama.cpp

commit 4e5116f47619dac4180c3007ef02a383f347554c
Author: eddiechen <Echen1246@gmail.com>
Date:   Sun Nov 15 02:09:46 2026 -0800

    server : fix output_config.effort being dropped in /v1/messages (#32321)

diff --git a/tools/server/server-chat.cpp b/tools/server/server-chat.cpp
index 7b080d17a..4e4622baf 100644
--- a/tools/server/server-chat.cpp
+++ b/tools/server/server-chat.cpp
@@ -659,6 +659,15 @@ json server_chat_convert_anthropic_to_oai(const json & body) {
         }
     }

+    // Handle Anthropic-specific output_config param
+    if (body.contains("output_config")) {
+        json output_config = json_value(body, "output_config", json::object());
+        std::string effort = json_value(output_config, "effort", std::string());
+        if (!effort.empty()) {
+            oai_body["reasoning_effort"] = effort;
+        }
+    }
+
     // Handle Anthropic-specific metadata param
     if (body.contains("metadata")) {
         json metadata = json_value(body, "metadata", json::object());
diff --git a/tools/server/tests/unit/test_compat_anthropic.py b/tools/server/tests/unit/test_compat_anthropic.py
index 220417745..2346de02e 100644
--- a/tools/server/tests/unit/test_compat_anthropic.py
+++ b/tools/server/tests/unit/test_compat_anthropic.py
@@ -851,6 +851,32 @@ def test_anthropic_thinking():
     assert res.body["type"] == "message"


+@pytest.mark.parametrize("effort", ["low", "high"])
+def test_anthropic_output_config_effort(effort):
+    """output_config.effort must reach the chat template, same as chat_template_kwargs.reasoning_effort"""
+    global server
+    server.jinja = True
+    server.chat_template_file = '../../../models/templates/openai-gpt-oss-120b.jinja'
+    server.start()
+
+    def count_tokens(extra):
+        res = server.make_request("POST", "/v1/messages/count_tokens", data={
+            "model": "test",
+            "messages": [{"role": "user", "content": "Hello"}],
+            **extra,
+        })
+        assert res.status_code == 200, res.body
+        return res.body["input_tokens"]
+
+    n_default = count_tokens({})
+    n_kwargs = count_tokens({"chat_template_kwargs": {"reasoning_effort": effort}})
+    n_output_config = count_tokens({"thinking": {"type": "adaptive"}, "output_config": {"effort": effort}})
+
+    # the template renders "Reasoning: medium" by default, so the effort must change the prompt
+    assert n_kwargs != n_default
+    assert n_output_config == n_kwargs
+
+
 def test_anthropic_metadata():
     """Test metadata parameter"""
     server.start()