fix(cli): handle Reasoning content and fix streaming thinking display (#7296)

Signed-off-by: rabi <ramishra@redhat.com>
This commit is contained in:
Rabi Mishra
2026-02-18 21:06:51 +05:30
committed by GitHub
parent a11b16f6d7
commit f4814843b3
2 changed files with 55 additions and 20 deletions
+2 -1
View File
@@ -967,6 +967,7 @@ impl CliSession {
let mut progress_bars = output::McpSpinners::new();
let cancel_token_clone = cancel_token.clone();
let mut markdown_buffer = streaming_buffer::MarkdownBuffer::new();
let mut thinking_header_shown = false;
use futures::StreamExt;
loop {
@@ -1039,7 +1040,7 @@ impl CliSession {
if is_stream_json_mode {
emit_stream_event(&StreamEvent::Message { message: message.clone() });
} else if !is_json_mode {
output::render_message_streaming(&message, &mut markdown_buffer, self.debug);
output::render_message_streaming(&message, &mut markdown_buffer, &mut thinking_header_shown, self.debug);
}
}
}
+53 -19
View File
@@ -16,7 +16,7 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{Error, IsTerminal, Write};
use std::path::Path;
use std::sync::Arc;
use std::sync::{Arc, LazyLock};
use std::time::Duration;
use super::streaming_buffer::MarkdownBuffer;
@@ -238,16 +238,9 @@ pub fn render_message(message: &Message, debug: bool) {
MessageContent::Image(image) => {
println!("Image: [data: {}, type: {}]", image.data, image.mime_type);
}
MessageContent::Thinking(thinking) => {
if std::env::var("GOOSE_CLI_SHOW_THINKING").is_ok()
&& std::io::stdout().is_terminal()
{
println!("\n{}", style("Thinking:").dim().italic());
print_markdown(&thinking.thinking, theme);
}
}
MessageContent::Thinking(t) => render_thinking(&t.thinking, theme),
MessageContent::Reasoning(r) => render_thinking(&r.text, theme),
MessageContent::RedactedThinking(_) => {
// For redacted thinking, print thinking was redacted
println!("\n{}", style("Thinking:").dim().italic());
print_markdown("Thinking was redacted", theme);
}
@@ -276,10 +269,22 @@ pub fn render_message(message: &Message, debug: bool) {
/// Render a streaming message, using a buffer to accumulate text content
/// and only render when markdown constructs are complete.
pub fn render_message_streaming(message: &Message, buffer: &mut MarkdownBuffer, debug: bool) {
pub fn render_message_streaming(
message: &Message,
buffer: &mut MarkdownBuffer,
thinking_header_shown: &mut bool,
debug: bool,
) {
let theme = get_theme();
for content in &message.content {
if !matches!(
content,
MessageContent::Thinking(_) | MessageContent::Reasoning(_)
) {
*thinking_header_shown = false;
}
match content {
MessageContent::Text(text) => {
if let Some(safe_content) = buffer.push(&text.text) {
@@ -312,14 +317,11 @@ pub fn render_message_streaming(message: &Message, buffer: &mut MarkdownBuffer,
flush_markdown_buffer(buffer, theme);
println!("Image: [data: {}, type: {}]", image.data, image.mime_type);
}
MessageContent::Thinking(thinking) => {
if std::env::var("GOOSE_CLI_SHOW_THINKING").is_ok()
&& std::io::stdout().is_terminal()
{
flush_markdown_buffer(buffer, theme);
println!("\n{}", style("Thinking:").dim().italic());
print_markdown(&thinking.thinking, theme);
}
MessageContent::Thinking(t) => {
render_thinking_streaming(&t.thinking, buffer, thinking_header_shown, theme);
}
MessageContent::Reasoning(r) => {
render_thinking_streaming(&r.text, buffer, thinking_header_shown, theme);
}
MessageContent::RedactedThinking(_) => {
flush_markdown_buffer(buffer, theme);
@@ -410,6 +412,38 @@ pub fn goose_mode_message(text: &str) {
println!("\n{}", style(text).yellow(),);
}
static SHOW_THINKING: LazyLock<bool> = LazyLock::new(|| {
std::env::var("GOOSE_CLI_SHOW_THINKING").is_ok() && std::io::stdout().is_terminal()
});
fn should_show_thinking() -> bool {
*SHOW_THINKING
}
fn render_thinking(text: &str, theme: Theme) {
if should_show_thinking() {
println!("\n{}", style("Thinking:").dim().italic());
print_markdown(text, theme);
}
}
fn render_thinking_streaming(
text: &str,
buffer: &mut MarkdownBuffer,
header_shown: &mut bool,
theme: Theme,
) {
if should_show_thinking() {
flush_markdown_buffer(buffer, theme);
if !*header_shown {
println!("\n{}", style("Thinking:").dim().italic());
*header_shown = true;
}
print!("{}", style(text).dim());
let _ = std::io::stdout().flush();
}
}
fn render_tool_request(req: &ToolRequest, theme: Theme, debug: bool) {
match &req.tool_call {
Ok(call) => match call.name.to_string().as_str() {