From b2eaf1850f28f81653999ad422e0889b05aa9548 Mon Sep 17 00:00:00 2001 From: rabi Date: Wed, 18 Feb 2026 09:33:37 +0530 Subject: [PATCH] fix(openai): support "reasoning" field alias in streaming deltas Add serde alias so both "reasoning" (vLLM, see vllm-project/vllm#27752) and "reasoning_content" (DeepSeek, SGLang) are recognized in streaming deltas. Once "reasoning" becomes the standard, it should become the primary field name. Change-Id: Ie24a7624903e9243c470783b0f482e2cdbf8b26c Signed-off-by: rabi --- crates/goose/src/providers/formats/openai.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/goose/src/providers/formats/openai.rs b/crates/goose/src/providers/formats/openai.rs index 567ce0cf7d2..cfbbb80c223 100644 --- a/crates/goose/src/providers/formats/openai.rs +++ b/crates/goose/src/providers/formats/openai.rs @@ -53,6 +53,7 @@ struct Delta { role: Option, tool_calls: Option>, reasoning_details: Option>, + #[serde(alias = "reasoning")] reasoning_content: Option, } @@ -338,8 +339,11 @@ pub fn response_to_message(response: &Value) -> anyhow::Result { let mut content = Vec::new(); - // Capture reasoning_content if present (for DeepSeek reasoning models) - if let Some(reasoning_content) = original.get("reasoning_content") { + // Capture reasoning content if present (DeepSeek uses "reasoning_content", vLLM uses "reasoning") + let reasoning_value = original + .get("reasoning_content") + .or_else(|| original.get("reasoning")); + if let Some(reasoning_content) = reasoning_value { if let Some(reasoning_str) = reasoning_content.as_str() { if !reasoning_str.is_empty() { content.push(MessageContent::reasoning(reasoning_str));