More no-window flags (#7122)

This commit is contained in:
Jack Amadeo
2026-02-11 12:43:18 -05:00
committed by GitHub
parent 1aacd56225
commit fb47728f1b
12 changed files with 90 additions and 3 deletions
@@ -5,8 +5,10 @@ use goose::recipe::RECIPE_FILE_EXTENSIONS;
use serde::{Deserialize, Serialize};
use goose::recipe::read_recipe_file_content::RecipeFile;
use goose::subprocess::SubprocessExt;
use std::env;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
@@ -104,6 +106,7 @@ pub fn ensure_gh_authenticated() -> Result<()> {
// Check authentication status
let status = Command::new("gh")
.args(["auth", "status"])
.set_no_window()
.status()
.map_err(|_| {
anyhow::anyhow!("Failed to run `gh auth status`. Make sure you have `gh` installed.")
@@ -151,6 +154,7 @@ fn ensure_repo_cloned(recipe_repo_full_name: &str) -> Result<PathBuf> {
let status = Command::new("gh")
.args(["repo", "clone", recipe_repo_full_name])
.current_dir(local_repo_parent_path.clone())
.set_no_window()
.status()
.map_err(|_: std::io::Error| anyhow::anyhow!(error_message.clone()))?;
@@ -167,6 +171,7 @@ fn fetch_origin(local_repo_path: &Path) -> Result<()> {
let status = Command::new("git")
.args(["fetch", "origin"])
.current_dir(local_repo_path)
.set_no_window()
.status()
.map_err(|_| anyhow::anyhow!(error_message.clone()))?;
@@ -190,6 +195,7 @@ fn get_folder_from_github(local_repo_path: &Path, recipe_name: &str) -> Result<P
.args(["archive", &ref_and_path])
.current_dir(local_repo_path)
.stdout(Stdio::piped())
.set_no_window()
.spawn()?;
let stdout = archive_output
@@ -230,6 +236,7 @@ fn discover_github_recipes(repo: &str) -> Result<Vec<RecipeInfo>> {
// Get repository contents using GitHub CLI
let output = Command::new("gh")
.args(["api", &format!("repos/{}/contents", repo)])
.set_no_window()
.output()
.map_err(|e| anyhow!("Failed to fetch repository contents using 'gh api' command (executed when GOOSE_RECIPE_GITHUB_REPO is configured). This requires GitHub CLI (gh) to be installed and authenticated. Error: {}", e))?;
@@ -269,6 +276,7 @@ fn check_github_directory_for_recipe(repo: &str, dir_name: &str) -> Result<Recip
// Check directory contents for recipe files
let output = Command::new("gh")
.args(["api", &format!("repos/{}/contents/{}", repo, dir_name)])
.set_no_window()
.output()
.map_err(|e| anyhow!("Failed to check directory contents: {}", e))?;
@@ -306,6 +314,7 @@ fn get_github_recipe_info(repo: &str, dir_name: &str, recipe_filename: &str) ->
"api",
&format!("repos/{}/contents/{}/{}", repo, dir_name, recipe_filename),
])
.set_no_window()
.output()
.map_err(|e| anyhow!("Failed to get recipe file content: {}", e))?;
+3
View File
@@ -6,6 +6,8 @@ use goose::conversation::message::{
ActionRequiredData, Message, MessageContent, ToolRequest, ToolResponse,
};
use goose::providers::canonical::maybe_get_canonical_model;
#[cfg(target_os = "windows")]
use goose::subprocess::SubprocessExt;
use goose::utils::safe_truncate;
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use rmcp::model::{CallToolRequestParams, JsonObject, PromptArgument};
@@ -179,6 +181,7 @@ pub fn run_status_hook(status: &str) {
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.set_no_window()
.status();
#[cfg(not(target_os = "windows"))]
@@ -1,3 +1,4 @@
use crate::subprocess::SubprocessExt;
use etcetera::{choose_app_strategy, AppStrategy};
use indoc::{formatdoc, indoc};
use reqwest::{Client, Url};
@@ -710,6 +711,7 @@ impl ComputerControllerServer {
.arg(&command)
.env("GOOSE_TERMINAL", "1")
.env("AGENT", "goose")
.set_no_window()
.output()
.await
.map_err(|e| {
@@ -725,6 +727,7 @@ impl ComputerControllerServer {
.arg(&command)
.env("GOOSE_TERMINAL", "1")
.env("AGENT", "goose")
.set_no_window()
.output()
.await
.map_err(|e| {
@@ -1,4 +1,5 @@
use super::SystemAutomation;
use crate::subprocess::SubprocessExt;
use std::path::PathBuf;
use std::process::Command;
@@ -13,6 +14,7 @@ impl SystemAutomation for WindowsAutomation {
.arg(script)
.env("GOOSE_TERMINAL", "1")
.env("AGENT", "goose")
.set_no_window()
.output()?;
Ok(String::from_utf8_lossy(&output.stdout).into_owned())
+3
View File
@@ -1,3 +1,4 @@
use crate::subprocess::SubprocessExt;
use anyhow::Result;
use std::env;
use std::path::PathBuf;
@@ -81,12 +82,14 @@ async fn get_windows_path_async(shell: &str) -> Result<String> {
"pwsh" | "powershell" => {
Command::new(shell)
.args(["-NoLogo", "-Command", "$env:PATH"])
.set_no_window()
.output()
.await
}
_ => {
Command::new(shell)
.args(["/c", "echo %PATH%"])
.set_no_window()
.output()
.await
}
+3
View File
@@ -1,3 +1,4 @@
use crate::subprocess::SubprocessExt;
use std::{env, ffi::OsString, process::Stdio};
#[cfg(unix)]
@@ -111,6 +112,7 @@ pub fn configure_shell_command(
working_dir: Option<&std::path::Path>,
) -> tokio::process::Command {
let mut command_builder = tokio::process::Command::new(&shell_config.executable);
command_builder.set_no_window();
if let Some(dir) = working_dir {
command_builder.current_dir(dir);
@@ -177,6 +179,7 @@ pub async fn kill_process_group(
// Use taskkill to kill the process tree on Windows
let _kill_result = tokio::process::Command::new("taskkill")
.args(&["/F", "/T", "/PID", &pid.to_string()])
.set_no_window()
.output()
.await;
}
+1
View File
@@ -14,6 +14,7 @@ pub mod computercontroller;
pub mod developer;
pub mod mcp_server_runner;
mod memory;
pub mod subprocess;
pub mod tutorial;
pub use autovisualiser::AutoVisualiserRouter;
+30
View File
@@ -0,0 +1,30 @@
use tokio::process::Command;
#[cfg(windows)]
const CREATE_NO_WINDOW_FLAG: u32 = 0x08000000;
pub trait SubprocessExt {
fn set_no_window(&mut self) -> &mut Self;
}
impl SubprocessExt for Command {
fn set_no_window(&mut self) -> &mut Self {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
self.creation_flags(CREATE_NO_WINDOW_FLAG);
}
self
}
}
impl SubprocessExt for std::process::Command {
fn set_no_window(&mut self) -> &mut Self {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
self.creation_flags(CREATE_NO_WINDOW_FLAG);
}
self
}
}
+4
View File
@@ -6,6 +6,8 @@ use tokio::process::Command;
use tokio::sync::Mutex;
use tracing::{debug, info, warn};
use crate::subprocess::SubprocessExt;
use crate::agents::types::SessionConfig;
use crate::agents::types::{
RetryConfig, SuccessCheck, DEFAULT_ON_FAILURE_TIMEOUT_SECONDS, DEFAULT_RETRY_TIMEOUT_SECONDS,
@@ -243,6 +245,8 @@ pub async fn execute_shell_command(
cmd
};
cmd.set_no_window();
let output = cmd
.stdout(Stdio::piped())
.stderr(Stdio::piped())
+3
View File
@@ -4,6 +4,8 @@ use crate::config::paths::Paths;
use crate::config::{get_enabled_extensions, Config};
use crate::session::session_manager::CURRENT_SCHEMA_VERSION;
use crate::session::SessionManager;
#[cfg(target_os = "windows")]
use crate::subprocess::SubprocessExt;
use chrono::{DateTime, Utc};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
@@ -141,6 +143,7 @@ fn get_platform_version() -> Option<String> {
{
std::process::Command::new("cmd")
.args(["/C", "ver"])
.set_no_window()
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
+2
View File
@@ -1,3 +1,4 @@
use crate::subprocess::SubprocessExt;
use chrono;
use serde::Deserialize;
use std::sync::Arc;
@@ -134,6 +135,7 @@ impl AzureAuth {
"--resource",
"https://cognitiveservices.azure.com",
])
.set_no_window()
.output()
.await
.map_err(|e| AuthError::TokenExchange(format!("Failed to execute Azure CLI: {}", e)))?;
+27 -3
View File
@@ -3,13 +3,37 @@ use tokio::process::Command;
#[cfg(windows)]
const CREATE_NO_WINDOW_FLAG: u32 = 0x08000000;
pub trait SubprocessExt {
fn set_no_window(&mut self) -> &mut Self;
}
impl SubprocessExt for Command {
fn set_no_window(&mut self) -> &mut Self {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
self.creation_flags(CREATE_NO_WINDOW_FLAG);
}
self
}
}
impl SubprocessExt for std::process::Command {
fn set_no_window(&mut self) -> &mut Self {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
self.creation_flags(CREATE_NO_WINDOW_FLAG);
}
self
}
}
#[allow(unused_variables)]
pub fn configure_subprocess(command: &mut Command) {
// Isolate subprocess into its own process group so it does not receive
// SIGINT when the user presses Ctrl+C in the terminal.
#[cfg(unix)]
command.process_group(0);
#[cfg(windows)]
command.creation_flags(CREATE_NO_WINDOW_FLAG);
command.set_no_window();
}