diff --git a/src-tauri/crates/tt-application/src/services/chat_completion_service/payload/deepseek.rs b/src-tauri/crates/tt-application/src/services/chat_completion_service/payload/deepseek.rs index 78633758..22f5abdc 100644 --- a/src-tauri/crates/tt-application/src/services/chat_completion_service/payload/deepseek.rs +++ b/src-tauri/crates/tt-application/src/services/chat_completion_service/payload/deepseek.rs @@ -55,7 +55,7 @@ pub(super) fn build(mut payload: Map) -> Result<(String, Value), } if thinking_mode == Some(DeepSeekThinkingMode::Enabled) { - ensure_tool_context_reasoning_content(&mut processed)?; + ensure_tool_context_reasoning_content(&mut processed, has_tools)?; } let processed = Value::Array(processed); @@ -149,18 +149,22 @@ fn apply_thinking_mode( } } -fn ensure_tool_context_reasoning_content(messages: &mut [Value]) -> Result<(), ApplicationError> { - let has_tool_context = messages.iter().any(|message| { - let Some(message_object) = message.as_object() else { - return false; - }; +fn ensure_tool_context_reasoning_content( + messages: &mut [Value], + has_tools: bool, +) -> Result<(), ApplicationError> { + let has_tool_context = has_tools + || messages.iter().any(|message| { + let Some(message_object) = message.as_object() else { + return false; + }; - message_object - .get("tool_calls") - .and_then(Value::as_array) - .is_some_and(|calls| !calls.is_empty()) - || message_object.get("role").and_then(Value::as_str) == Some("tool") - }); + message_object + .get("tool_calls") + .and_then(Value::as_array) + .is_some_and(|calls| !calls.is_empty()) + || message_object.get("role").and_then(Value::as_str) == Some("tool") + }); if !has_tool_context { return Ok(()); @@ -261,6 +265,39 @@ mod tests { assert_eq!(last.get("prefix").and_then(Value::as_bool), Some(true)); } + #[test] + fn deepseek_thinking_with_tools_fills_terminal_assistant_reasoning_content() { + let payload = json!({ + "model": "deepseek-v4-flash", + "messages": [ + {"role":"user","content":"continue"}, + {"role":"assistant","content":"Answer:"} + ], + "tools": [{ + "type": "function", + "function": { + "name": "noop", + "description": "Do nothing", + "parameters": {"type": "object", "properties": {}} + } + }], + "include_reasoning": true, + "chat_completion_source": "deepseek" + }) + .as_object() + .cloned() + .expect("payload must be object"); + + let (_, upstream) = build(payload).expect("payload should build"); + + assert_eq!( + upstream + .pointer("/messages/1/reasoning_content") + .and_then(Value::as_str), + Some("") + ); + } + #[test] fn deepseek_v4_enables_thinking_and_maps_effort() { let payload = json!({