diff --git a/crates/goose-cli/Cargo.toml b/crates/goose-cli/Cargo.toml index 745b4e962191..41cb85a604eb 100644 --- a/crates/goose-cli/Cargo.toml +++ b/crates/goose-cli/Cargo.toml @@ -47,7 +47,6 @@ chrono = "0.4" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json", "time"] } tracing-appender = "0.2" once_cell = "1.20.2" -winapi = { version = "0.3", features = ["wincred"], optional = true } [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["wincred"] } diff --git a/crates/goose-mcp/src/computercontroller/platform/macos.rs b/crates/goose-mcp/src/computercontroller/platform/macos.rs index 09c16567d690..c5d5694a6810 100644 --- a/crates/goose-mcp/src/computercontroller/platform/macos.rs +++ b/crates/goose-mcp/src/computercontroller/platform/macos.rs @@ -4,10 +4,6 @@ use std::process::Command; pub struct MacOSAutomation; -// MacOSAutomation is Send + Sync because it contains no shared state -unsafe impl Send for MacOSAutomation {} -unsafe impl Sync for MacOSAutomation {} - impl SystemAutomation for MacOSAutomation { fn execute_system_script(&self, script: &str) -> std::io::Result { let output = Command::new("osascript").arg("-e").arg(script).output()?; diff --git a/crates/goose-mcp/src/computercontroller/platform/windows.rs b/crates/goose-mcp/src/computercontroller/platform/windows.rs index 4e7c9e920d23..d2c386f6a561 100644 --- a/crates/goose-mcp/src/computercontroller/platform/windows.rs +++ b/crates/goose-mcp/src/computercontroller/platform/windows.rs @@ -4,10 +4,6 @@ use std::process::Command; pub struct WindowsAutomation; -// WindowsAutomation is Send + Sync because it contains no shared state -unsafe impl Send for WindowsAutomation {} -unsafe impl Sync for WindowsAutomation {} - impl SystemAutomation for WindowsAutomation { fn execute_system_script(&self, script: &str) -> std::io::Result { let output = Command::new("powershell") diff --git a/crates/goose-mcp/src/developer/mod.rs b/crates/goose-mcp/src/developer/mod.rs index 398e33178b70..bbc7c5f8cd7e 100644 --- a/crates/goose-mcp/src/developer/mod.rs +++ b/crates/goose-mcp/src/developer/mod.rs @@ -115,13 +115,13 @@ impl DeveloperRouter { Avoid commands that produce a large amount of output, and consider piping those outputs to files. **Important**: For searching files and code: - + Preferred: Use ripgrep (`rg`) when available - it respects .gitignore and is fast: - To locate a file by name: `rg --files | rg example.py` - To locate content inside files: `rg 'class Example'` - + Alternative Windows commands (if ripgrep is not installed): - - To locate a file by name: `dir /s /b example.py` + - To locate a file by name: `dir /s /b example.py` - To locate content inside files: `findstr /s /i "class Example" *.py` Note: Alternative commands may show ignored/hidden files that should be excluded. @@ -996,6 +996,69 @@ mod tests { assert!(result.is_ok()); } + #[tokio::test] + #[serial] + async fn test_text_editor_size_limits() { + // Create temp directory first so it stays in scope for the whole test + let temp_dir = tempfile::tempdir().unwrap(); + std::env::set_current_dir(&temp_dir).unwrap(); + + // Get router after setting current directory + let router = get_router().await; + + // Test file size limit + { + let large_file_path = temp_dir.path().join("large.txt"); + let large_file_str = large_file_path.to_str().unwrap(); + + // Create a file larger than 2MB + let content = "x".repeat(3 * 1024 * 1024); // 3MB + std::fs::write(&large_file_path, content).unwrap(); + + let result = router + .call_tool( + "text_editor", + json!({ + "command": "view", + "path": large_file_str + }), + ) + .await; + + assert!(result.is_err()); + let err = result.err().unwrap(); + assert!(matches!(err, ToolError::ExecutionError(_))); + assert!(err.to_string().contains("too large")); + } + + // Test character count limit + { + let many_chars_path = temp_dir.path().join("many_chars.txt"); + let many_chars_str = many_chars_path.to_str().unwrap(); + + // Create a file with more than 400K characters but less than 400KB + let content = "x".repeat(405_000); + std::fs::write(&many_chars_path, content).unwrap(); + + let result = router + .call_tool( + "text_editor", + json!({ + "command": "view", + "path": many_chars_str + }), + ) + .await; + + assert!(result.is_err()); + let err = result.err().unwrap(); + assert!(matches!(err, ToolError::ExecutionError(_))); + assert!(err.to_string().contains("too many characters")); + } + + // Let temp_dir drop naturally at end of scope + } + #[tokio::test] #[serial] async fn test_text_editor_write_and_view_file() {