open_ai: Support reasoning content (#43662)

Support for Kimi K2 Thinking

Release Notes:

- Added support for thinking traces when using OpenAI-API-compatible AI providers

---------

Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
This commit is contained in:
Aero 2026-01-21 18:08:59 +08:00 committed by GitHub
parent 5731066b6f
commit 7bd3075d53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 2 deletions

View file

@ -426,7 +426,14 @@ pub fn into_open_ai(
for content in message.content {
match content {
MessageContent::Text(text) | MessageContent::Thinking { text, .. } => {
if !text.trim().is_empty() {
let should_add = if message.role == Role::User {
// Including whitespace-only user messages can cause error with OpenAI compatible APIs
// See https://github.com/zed-industries/zed/issues/40097
!text.trim().is_empty()
} else {
!text.is_empty()
};
if should_add {
add_message_content_part(
open_ai::MessagePart::Text { text },
message.role,
@ -792,8 +799,18 @@ impl OpenAiEventMapper {
};
if let Some(delta) = choice.delta.as_ref() {
if let Some(reasoning_content) = delta.reasoning_content.clone() {
if !reasoning_content.is_empty() {
events.push(Ok(LanguageModelCompletionEvent::Thinking {
text: reasoning_content,
signature: None,
}));
}
}
if let Some(content) = delta.content.clone() {
events.push(Ok(LanguageModelCompletionEvent::Text(content)));
if !content.is_empty() {
events.push(Ok(LanguageModelCompletionEvent::Text(content)));
}
}
if let Some(tool_calls) = delta.tool_calls.as_ref() {

View file

@ -463,6 +463,8 @@ pub struct ResponseMessageDelta {
pub content: Option<String>,
#[serde(default, skip_serializing_if = "is_none_or_empty")]
pub tool_calls: Option<Vec<ToolCallChunk>>,
#[serde(default, skip_serializing_if = "is_none_or_empty")]
pub reasoning_content: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]