Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 26 additions & 20 deletions crates/goose-mcp/src/computercontroller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ use tokio::process::Command;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;

#[cfg(windows)]
use std::os::windows::process::CommandExt;

#[cfg(windows)]
const CREATE_NO_WINDOW: u32 = 0x08000000;

mod docx_tool;
mod pdf_tool;
mod xlsx_tool;
Expand Down Expand Up @@ -703,35 +709,35 @@ impl ComputerControllerServer {
let output = match language {
ScriptLanguage::Powershell => {
// For PowerShell, we need to use -File instead of -Command
Command::new("powershell")
.arg("-NoProfile")
let mut cmd = Command::new("powershell");
cmd.arg("-NoProfile")
.arg("-NonInteractive")
.arg("-File")
.arg(&command)
.env("GOOSE_TERMINAL", "1")
.output()
.await
.map_err(|e| {
ErrorData::new(
ErrorCode::INTERNAL_ERROR,
format!("Failed to run script: {}", e),
None,
)
})?
.env("GOOSE_TERMINAL", "1");
#[cfg(windows)]
cmd.creation_flags(CREATE_NO_WINDOW);
cmd.output().await.map_err(|e| {
ErrorData::new(
ErrorCode::INTERNAL_ERROR,
format!("Failed to run script: {}", e),
None,
)
})?
}
_ => Command::new(shell)
.arg(shell_arg)
.arg(&command)
.env("GOOSE_TERMINAL", "1")
.output()
.await
.map_err(|e| {
_ => {
let mut cmd = Command::new(shell);
cmd.arg(shell_arg).arg(&command).env("GOOSE_TERMINAL", "1");
#[cfg(windows)]
cmd.creation_flags(CREATE_NO_WINDOW);
cmd.output().await.map_err(|e| {
ErrorData::new(
ErrorCode::INTERNAL_ERROR,
format!("Failed to run script: {}", e),
None,
)
})?,
})?
}
};

let output_str = String::from_utf8_lossy(&output.stdout).into_owned();
Expand Down
4 changes: 4 additions & 0 deletions crates/goose-mcp/src/computercontroller/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use super::SystemAutomation;
use std::path::PathBuf;
use std::process::Command;

use std::os::windows::process::CommandExt;
const CREATE_NO_WINDOW: u32 = 0x08000000;

pub struct WindowsAutomation;

impl SystemAutomation for WindowsAutomation {
Expand All @@ -12,6 +15,7 @@ impl SystemAutomation for WindowsAutomation {
.arg("-Command")
.arg(script)
.env("GOOSE_TERMINAL", "1")
.creation_flags(CREATE_NO_WINDOW)
.output()?;

Ok(String::from_utf8_lossy(&output.stdout).into_owned())
Expand Down
24 changes: 16 additions & 8 deletions crates/goose-mcp/src/developer/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use std::path::PathBuf;
use tokio::process::Command;
use tokio::sync::OnceCell;

#[cfg(windows)]
use std::os::windows::process::CommandExt;

#[cfg(windows)]
const CREATE_NO_WINDOW: u32 = 0x08000000;

static SHELL_PATH_DIRS: OnceCell<Result<Vec<PathBuf>, anyhow::Error>> = OnceCell::const_new();

pub async fn get_shell_path_dirs() -> Result<&'static Vec<PathBuf>> {
Expand Down Expand Up @@ -79,16 +85,18 @@ async fn get_windows_path_async(shell: &str) -> Result<String> {

let output = match shell_name {
"pwsh" | "powershell" => {
Command::new(shell)
.args(["-NoLogo", "-Command", "$env:PATH"])
.output()
.await
let mut cmd = Command::new(shell);
cmd.args(["-NoLogo", "-Command", "$env:PATH"]);
#[cfg(windows)]
cmd.creation_flags(CREATE_NO_WINDOW);
cmd.output().await
}
_ => {
Command::new(shell)
.args(["/c", "echo %PATH%"])
.output()
.await
let mut cmd = Command::new(shell);
cmd.args(["/c", "echo %PATH%"]);
#[cfg(windows)]
cmd.creation_flags(CREATE_NO_WINDOW);
cmd.output().await
}
};

Expand Down
19 changes: 15 additions & 4 deletions crates/goose-mcp/src/developer/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use std::{env, ffi::OsString, process::Stdio};
#[allow(unused_imports)] // False positive: trait is used for process_group method
use std::os::unix::process::CommandExt;

#[cfg(windows)]
use std::os::windows::process::CommandExt;

#[cfg(windows)]
const CREATE_NO_WINDOW: u32 = 0x08000000;

#[derive(Debug, Clone)]
pub struct ShellConfig {
pub executable: String,
Expand Down Expand Up @@ -132,6 +138,11 @@ pub fn configure_shell_command(
.args(&shell_config.args)
.arg(command);

#[cfg(windows)]
{
command_builder.creation_flags(CREATE_NO_WINDOW);
}

// On Unix systems, create a new process group so we can kill child processes
#[cfg(unix)]
{
Expand Down Expand Up @@ -170,10 +181,10 @@ pub async fn kill_process_group(
{
if let Some(pid) = pid {
// Use taskkill to kill the process tree on Windows
let _kill_result = tokio::process::Command::new("taskkill")
.args(&["/F", "/T", "/PID", &pid.to_string()])
.output()
.await;
let mut kill_cmd = tokio::process::Command::new("taskkill")
.args(["/F", "/T", "/PID", &pid.to_string()])
.creation_flags(CREATE_NO_WINDOW);
let _kill_result = kill_cmd.output().await;
}

// Return the result of tokio's kill
Expand Down