Suppress ansi with pipes (#3775)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -59,3 +59,5 @@ do_not_version/
|
|||||||
/ui/desktop/src/bin/goose-scheduler-executor
|
/ui/desktop/src/bin/goose-scheduler-executor
|
||||||
/ui/desktop/src/bin/goose
|
/ui/desktop/src/bin/goose
|
||||||
/.env
|
/.env
|
||||||
|
|
||||||
|
/working_dir
|
||||||
|
|||||||
Generated
+7
-5
@@ -3379,6 +3379,7 @@ dependencies = [
|
|||||||
name = "goose-cli"
|
name = "goose-cli"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum 0.8.1",
|
"axum 0.8.1",
|
||||||
@@ -3396,6 +3397,7 @@ dependencies = [
|
|||||||
"goose-mcp",
|
"goose-mcp",
|
||||||
"http 1.2.0",
|
"http 1.2.0",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
|
"is-terminal",
|
||||||
"jsonschema",
|
"jsonschema",
|
||||||
"mcp-client",
|
"mcp-client",
|
||||||
"mcp-core",
|
"mcp-core",
|
||||||
@@ -3631,9 +3633,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.4.0"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex"
|
name = "hex"
|
||||||
@@ -4246,11 +4248,11 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.15"
|
version = "0.4.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
|
checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.4.0",
|
"hermit-abi 0.5.2",
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ http = "1.0"
|
|||||||
webbrowser = "1.0"
|
webbrowser = "1.0"
|
||||||
indicatif = "0.17.11"
|
indicatif = "0.17.11"
|
||||||
tokio-util = "0.7.15"
|
tokio-util = "0.7.15"
|
||||||
|
is-terminal = "0.4.16"
|
||||||
|
anstream = "0.6.18"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["wincred"] }
|
winapi = { version = "0.3", features = ["wincred"] }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use anstream::println;
|
||||||
use console::style;
|
use console::style;
|
||||||
use goose::recipe::{Recipe, BUILT_IN_RECIPE_DIR_PARAM};
|
use goose::recipe::{Recipe, BUILT_IN_RECIPE_DIR_PARAM};
|
||||||
|
|
||||||
@@ -81,16 +82,16 @@ pub fn missing_parameters_command_line(missing_params: Vec<String>) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_recipe_info(recipe: &Recipe, params: Vec<(String, String)>) {
|
pub fn print_recipe_info(recipe: &Recipe, params: Vec<(String, String)>) {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
style("Loading recipe:").green().bold(),
|
style("Loading recipe:").green().bold(),
|
||||||
style(&recipe.title).green()
|
style(&recipe.title).green()
|
||||||
);
|
);
|
||||||
println!("{} {}", style("Description:").bold(), &recipe.description);
|
eprintln!("{} {}", style("Description:").bold(), &recipe.description);
|
||||||
|
|
||||||
if !params.is_empty() {
|
if !params.is_empty() {
|
||||||
println!("{}", style("Parameters used to load this recipe:").bold());
|
eprintln!("{}", style("Parameters used to load this recipe:").bold());
|
||||||
print_parameters_with_values(params.into_iter().collect());
|
print_parameters_with_values(params.into_iter().collect());
|
||||||
}
|
}
|
||||||
println!();
|
eprintln!();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use anstream::println;
|
||||||
use bat::WrappingMode;
|
use bat::WrappingMode;
|
||||||
use console::{style, Color};
|
use console::{style, Color};
|
||||||
use goose::config::Config;
|
use goose::config::Config;
|
||||||
@@ -11,11 +12,10 @@ use rmcp::model::PromptArgument;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::{Error, Write};
|
use std::io::{Error, IsTerminal, Write};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
// Re-export theme for use in main
|
// Re-export theme for use in main
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Theme {
|
pub enum Theme {
|
||||||
@@ -135,11 +135,15 @@ thread_local! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_thinking() {
|
pub fn show_thinking() {
|
||||||
THINKING.with(|t| t.borrow_mut().show());
|
if std::io::stdout().is_terminal() {
|
||||||
|
THINKING.with(|t| t.borrow_mut().show());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hide_thinking() {
|
pub fn hide_thinking() {
|
||||||
THINKING.with(|t| t.borrow_mut().hide());
|
if std::io::stdout().is_terminal() {
|
||||||
|
THINKING.with(|t| t.borrow_mut().hide());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_showing_thinking() -> bool {
|
pub fn is_showing_thinking() -> bool {
|
||||||
@@ -147,11 +151,13 @@ pub fn is_showing_thinking() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_thinking_message(s: &String) {
|
pub fn set_thinking_message(s: &String) {
|
||||||
THINKING.with(|t| {
|
if std::io::stdout().is_terminal() {
|
||||||
if let Some(spinner) = t.borrow_mut().spinner.as_mut() {
|
THINKING.with(|t| {
|
||||||
spinner.set_message(s);
|
if let Some(spinner) = t.borrow_mut().spinner.as_mut() {
|
||||||
}
|
spinner.set_message(s);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_message(message: &Message, debug: bool) {
|
pub fn render_message(message: &Message, debug: bool) {
|
||||||
@@ -166,7 +172,9 @@ pub fn render_message(message: &Message, debug: bool) {
|
|||||||
println!("Image: [data: {}, type: {}]", image.data, image.mime_type);
|
println!("Image: [data: {}, type: {}]", image.data, image.mime_type);
|
||||||
}
|
}
|
||||||
MessageContent::Thinking(thinking) => {
|
MessageContent::Thinking(thinking) => {
|
||||||
if std::env::var("GOOSE_CLI_SHOW_THINKING").is_ok() {
|
if std::env::var("GOOSE_CLI_SHOW_THINKING").is_ok()
|
||||||
|
&& std::io::stdout().is_terminal()
|
||||||
|
{
|
||||||
println!("\n{}", style("Thinking:").dim().italic());
|
println!("\n{}", style("Thinking:").dim().italic());
|
||||||
print_markdown(&thinking.thinking, theme);
|
print_markdown(&thinking.thinking, theme);
|
||||||
}
|
}
|
||||||
@@ -190,6 +198,10 @@ pub fn render_text(text: &str, color: Option<Color>, dim: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_text_no_newlines(text: &str, color: Option<Color>, dim: bool) {
|
pub fn render_text_no_newlines(text: &str, color: Option<Color>, dim: bool) {
|
||||||
|
if !std::io::stdout().is_terminal() {
|
||||||
|
println!("{}", text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mut styled_text = style(text);
|
let mut styled_text = style(text);
|
||||||
if dim {
|
if dim {
|
||||||
styled_text = styled_text.dim();
|
styled_text = styled_text.dim();
|
||||||
@@ -472,14 +484,18 @@ pub fn env_no_color() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_markdown(content: &str, theme: Theme) {
|
fn print_markdown(content: &str, theme: Theme) {
|
||||||
bat::PrettyPrinter::new()
|
if std::io::stdout().is_terminal() {
|
||||||
.input(bat::Input::from_bytes(content.as_bytes()))
|
bat::PrettyPrinter::new()
|
||||||
.theme(theme.as_str())
|
.input(bat::Input::from_bytes(content.as_bytes()))
|
||||||
.colored_output(env_no_color())
|
.theme(theme.as_str())
|
||||||
.language("Markdown")
|
.colored_output(env_no_color())
|
||||||
.wrapping_mode(WrappingMode::NoWrapping(true))
|
.language("Markdown")
|
||||||
.print()
|
.wrapping_mode(WrappingMode::NoWrapping(true))
|
||||||
.unwrap();
|
.print()
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
print!("{}", content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const INDENT: &str = " ";
|
const INDENT: &str = " ";
|
||||||
@@ -768,7 +784,7 @@ pub async fn display_cost_usage(
|
|||||||
) {
|
) {
|
||||||
if let Some(cost) = estimate_cost_usd(provider, model, input_tokens, output_tokens).await {
|
if let Some(cost) = estimate_cost_usd(provider, model, input_tokens, output_tokens).await {
|
||||||
use console::style;
|
use console::style;
|
||||||
println!(
|
eprintln!(
|
||||||
"Cost: {} USD ({} tokens: in {}, out {})",
|
"Cost: {} USD ({} tokens: in {}, out {})",
|
||||||
style(format!("${:.4}", cost)).cyan(),
|
style(format!("${:.4}", cost)).cyan(),
|
||||||
input_tokens + output_tokens,
|
input_tokens + output_tokens,
|
||||||
|
|||||||
Reference in New Issue
Block a user